r102986 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r102985‎ | r102986 | r102987 >
Date:14:33, 14 November 2011
Author:jeroendedauw
Status:deferred
Tags:
Comment:
Tag for version 0.1.2.
Modified paths:
  • /tags/extensions/Survey/REL_0_1_2 (added) (history)

Diff [purge]

Index: tags/extensions/Survey/REL_0_1_2/test/SurveyQuestionTest.php
@@ -0,0 +1,27 @@
 2+<?php
 3+
 4+/**
 5+ * SurveyQuestion test case.
 6+ *
 7+ * @ingroup Survey
 8+ * @since 0.1
 9+ *
 10+ * @licence GNU GPL v3
 11+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 12+ */
 13+class SurveyQuestionTest extends MediaWikiTestCase {
 14+
 15+ /**
 16+ * Tests SurveyQuestion::newFromUrlData and SurveyQuestion::toUrlData
 17+ */
 18+ public function testQuestionUrlSerialization() {
 19+ $question = new SurveyQuestion( 9001, 42, 'ohai there!', 0, true );
 20+
 21+ $this->assertEquals(
 22+ $question,
 23+ SurveyQuestion::newFromUrlData( $question->toUrlData() ),
 24+ "Serializaion test failed at " . __METHOD__
 25+ );
 26+ }
 27+
 28+}
Property changes on: tags/extensions/Survey/REL_0_1_2/test/SurveyQuestionTest.php
___________________________________________________________________
Added: svn:eol-style
129 + native
Index: tags/extensions/Survey/REL_0_1_2/Survey.settings.php
@@ -0,0 +1,83 @@
 2+<?php
 3+
 4+/**
 5+ * File defining the settings for the Survey extension.
 6+ * More info can be found at http://www.mediawiki.org/wiki/Extension:Survey#Settings
 7+ *
 8+ * NOTICE:
 9+ * Changing one of these settings can be done by assigning to $egSurveySettings,
 10+ * AFTER the inclusion of the extension itself.
 11+ *
 12+ * @since 0.1
 13+ *
 14+ * @file Survey.settings.php
 15+ * @ingroup Survey
 16+ *
 17+ * @licence GNU GPL v3+
 18+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 19+ */
 20+class SurveySettings {
 21+
 22+ /**
 23+ * Returns the default values for the settings.
 24+ * setting name (string) => setting value (mixed)
 25+ *
 26+ * @since 0.1
 27+ *
 28+ * @return array
 29+ */
 30+ protected static function getDefaultSettings() {
 31+ return array(
 32+ 'JSDebug' => false,
 33+ 'defaultEnabled' => false,
 34+ 'defaultUserType' => Survey::$USER_ALL,
 35+ 'defaultNamespaces' => array(),
 36+ 'defaultRatio' => 100,
 37+ 'defaultExpiry' => 60 * 60 * 24 * 30,
 38+ 'defaultMinPages' => 0
 39+ );
 40+ }
 41+
 42+ /**
 43+ * Retruns an array with all settings after making sure they are
 44+ * initialized (ie set settings have been merged with the defaults).
 45+ * setting name (string) => setting value (mixed)
 46+ *
 47+ * @since 0.1
 48+ *
 49+ * @return array
 50+ */
 51+ public static function getSettings() {
 52+ static $settings = false;
 53+
 54+ if ( $settings === false ) {
 55+ $settings = array_merge(
 56+ self::getDefaultSettings(),
 57+ $GLOBALS['egSurveySettings']
 58+ );
 59+ }
 60+
 61+ return $settings;
 62+ }
 63+
 64+ /**
 65+ * Gets the value of the specified setting.
 66+ *
 67+ * @since 0.1
 68+ *
 69+ * @param string $settingName
 70+ *
 71+ * @throws MWException
 72+ * @return mixed
 73+ */
 74+ public static function get( $settingName ) {
 75+ $settings = self::getSettings();
 76+
 77+ if ( !array_key_exists( $settingName, $settings ) ) {
 78+ throw new MWException( 'Attempt to get non-existing setting "' . $settingName . '"' );
 79+ }
 80+
 81+ return $settings[$settingName];
 82+ }
 83+
 84+}
Property changes on: tags/extensions/Survey/REL_0_1_2/Survey.settings.php
___________________________________________________________________
Added: svn:eol-style
185 + native
Index: tags/extensions/Survey/REL_0_1_2/Survey.php
@@ -0,0 +1,202 @@
 2+<?php
 3+
 4+/**
 5+ * Initialization file for the Survey extension.
 6+ *
 7+ * Documentation: http://www.mediawiki.org/wiki/Extension:Survey
 8+ * Support http://www.mediawiki.org/wiki/Extension_talk:Survey
 9+ * Source code: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Survey
 10+ *
 11+ * @file Survey.php
 12+ * @ingroup Survey
 13+ *
 14+ * @licence GNU GPL v3+
 15+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 16+ */
 17+
 18+/**
 19+ * This documenation group collects source code files belonging to Survey.
 20+ *
 21+ * @defgroup Survey Survey
 22+ */
 23+
 24+if ( !defined( 'MEDIAWIKI' ) ) {
 25+ die( 'Not an entry point.' );
 26+}
 27+
 28+if ( version_compare( $wgVersion, '1.17', '<' ) ) {
 29+ die( '<b>Error:</b> Survey requires MediaWiki 1.17 or above.' );
 30+}
 31+
 32+define( 'Survey_VERSION', '0.1.2' );
 33+
 34+$wgExtensionCredits['other'][] = array(
 35+ 'path' => __FILE__,
 36+ 'name' => 'Survey',
 37+ 'version' => Survey_VERSION,
 38+ 'author' => array(
 39+ '[http://www.mediawiki.org/wiki/User:Jeroen_De_Dauw Jeroen De Dauw] for [http://www.wikiworks.com WikiWorks]',
 40+ ),
 41+ 'url' => 'http://www.mediawiki.org/wiki/Extension:Survey',
 42+ 'descriptionmsg' => 'survey-desc'
 43+);
 44+
 45+$wgExtensionMessagesFiles['Survey'] = dirname( __FILE__ ) . '/Survey.i18n.php';
 46+$wgExtensionMessagesFiles['SurveyAlias'] = dirname( __FILE__ ) . '/Survey.alias.php';
 47+
 48+$wgAutoloadClasses['SurveyHooks'] = dirname( __FILE__ ) . '/Survey.hooks.php';
 49+$wgAutoloadClasses['SurveySettings'] = dirname( __FILE__ ) . '/Survey.settings.php';
 50+
 51+$wgAutoloadClasses['ApiAddSurvey'] = dirname( __FILE__ ) . '/api/ApiAddSurvey.php';
 52+$wgAutoloadClasses['ApiDeleteSurvey'] = dirname( __FILE__ ) . '/api/ApiDeleteSurvey.php';
 53+$wgAutoloadClasses['ApiEditSurvey'] = dirname( __FILE__ ) . '/api/ApiEditSurvey.php';
 54+$wgAutoloadClasses['ApiQuerySurveyAnswers'] = dirname( __FILE__ ) . '/api/ApiQuerySurveyAnswers.php';
 55+$wgAutoloadClasses['ApiQuerySurveys'] = dirname( __FILE__ ) . '/api/ApiQuerySurveys.php';
 56+$wgAutoloadClasses['ApiQuerySurveySubmissions'] = dirname( __FILE__ ) . '/api/ApiQuerySurveySubmissions.php';
 57+$wgAutoloadClasses['ApiSubmitSurvey'] = dirname( __FILE__ ) . '/api/ApiSubmitSurvey.php';
 58+
 59+$wgAutoloadClasses['Survey'] = dirname( __FILE__ ) . '/includes/Survey.class.php';
 60+$wgAutoloadClasses['SurveyAnswer'] = dirname( __FILE__ ) . '/includes/SurveyAnswer.php';
 61+$wgAutoloadClasses['SurveyCompat'] = dirname( __FILE__ ) . '/includes/SurveyCompat.php';
 62+$wgAutoloadClasses['SurveyDBClass'] = dirname( __FILE__ ) . '/includes/SurveyDBClass.php';
 63+$wgAutoloadClasses['SurveyQuestion'] = dirname( __FILE__ ) . '/includes/SurveyQuestion.php';
 64+$wgAutoloadClasses['SurveySubmission'] = dirname( __FILE__ ) . '/includes/SurveySubmission.php';
 65+$wgAutoloadClasses['SurveyTag'] = dirname( __FILE__ ) . '/includes/SurveyTag.php';
 66+
 67+$wgAutoloadClasses['SpecialSurvey'] = dirname( __FILE__ ) . '/specials/SpecialSurvey.php';
 68+$wgAutoloadClasses['SpecialSurveyPage'] = dirname( __FILE__ ) . '/specials/SpecialSurveyPage.php';
 69+$wgAutoloadClasses['SpecialSurveys'] = dirname( __FILE__ ) . '/specials/SpecialSurveys.php';
 70+$wgAutoloadClasses['SpecialSurveyStats'] = dirname( __FILE__ ) . '/specials/SpecialSurveyStats.php';
 71+$wgAutoloadClasses['SpecialTakeSurvey'] = dirname( __FILE__ ) . '/specials/SpecialTakeSurvey.php';
 72+
 73+$wgSpecialPages['EditSurvey'] = 'SpecialSurvey';
 74+$wgSpecialPages['Surveys'] = 'SpecialSurveys';
 75+$wgSpecialPages['SurveyStats'] = 'SpecialSurveyStats';
 76+$wgSpecialPages['TakeSurvey'] = 'SpecialTakeSurvey';
 77+
 78+$wgSpecialPageGroups['EditSurvey'] = 'other';
 79+$wgSpecialPageGroups['Surveys'] = 'other';
 80+$wgSpecialPageGroups['SurveyStats'] = 'other';
 81+$wgSpecialPageGroups['TakeSurvey'] = 'other';
 82+
 83+$wgAPIModules['addsurvey'] = 'ApiAddSurvey';
 84+$wgAPIModules['deletesurvey'] = 'ApiDeleteSurvey';
 85+$wgAPIModules['editsurvey'] = 'ApiEditSurvey';
 86+$wgAPIModules['submitsurvey'] = 'ApiSubmitSurvey';
 87+$wgAPIListModules['surveys'] = 'ApiQuerySurveys';
 88+$wgAPIListModules['surveyanswers'] = 'ApiQuerySurveyAnswers';
 89+$wgAPIListModules['surveysubmissions'] = 'ApiQuerySurveySubmissions';
 90+
 91+$wgHooks['LoadExtensionSchemaUpdates'][] = 'SurveyHooks::onSchemaUpdate';
 92+$wgHooks['UnitTestsList'][] = 'SurveyHooks::registerUnitTests';
 93+$wgHooks['ParserFirstCallInit'][] = 'SurveyHooks::onParserFirstCallInit';
 94+$wgHooks['ArticleViewHeader'][] = 'SurveyHooks::onArticleViewHeader';
 95+$wgHooks['AdminLinks'][] = 'SurveyHooks::addToAdminLinks';
 96+
 97+$wgAvailableRights[] = 'surveyadmin';
 98+$wgAvailableRights[] = 'surveysubmit';
 99+
 100+# Users that can manage the surveys.
 101+$wgGroupPermissions['*' ]['surveyadmin'] = false;
 102+$wgGroupPermissions['user' ]['surveyadmin'] = false;
 103+$wgGroupPermissions['autoconfirmed']['surveyadmin'] = false;
 104+$wgGroupPermissions['bot' ]['surveyadmin'] = false;
 105+$wgGroupPermissions['sysop' ]['surveyadmin'] = true;
 106+
 107+# Users that can submit surveys.
 108+$wgGroupPermissions['*' ]['surveysubmit'] = true;
 109+$wgGroupPermissions['user' ]['surveysubmit'] = true;
 110+$wgGroupPermissions['autoconfirmed']['surveysubmit'] = true;
 111+$wgGroupPermissions['bot' ]['surveysubmit'] = false;
 112+$wgGroupPermissions['sysop' ]['surveysubmit'] = true;
 113+
 114+$moduleTemplate = array(
 115+ 'localBasePath' => dirname( __FILE__ ) . '/resources',
 116+ 'remoteExtPath' => 'Survey/resources'
 117+);
 118+
 119+$wgResourceModules['ext.survey'] = $moduleTemplate + array(
 120+ 'scripts' => array(
 121+ 'ext.survey.js'
 122+ ),
 123+);
 124+
 125+$wgResourceModules['ext.survey.special.surveys'] = $moduleTemplate + array(
 126+ 'scripts' => array(
 127+ 'ext.survey.special.surveys.js'
 128+ ),
 129+ 'dependencies' => array( 'ext.survey' ),
 130+ 'messages' => array(
 131+ 'surveys-special-confirm-delete',
 132+ 'surveys-special-delete-failed',
 133+ )
 134+);
 135+
 136+$wgResourceModules['ext.survey.special.survey'] = $moduleTemplate + array(
 137+ 'scripts' => array(
 138+ 'ext.survey.answerSelector.js',
 139+ 'ext.survey.special.survey.js'
 140+ ),
 141+ 'styles' => array(
 142+ 'ext.survey.special.survey.css'
 143+ ),
 144+ 'dependencies' => array( 'ext.survey', 'jquery.ui.button' ),
 145+ 'messages' => array(
 146+ 'survey-question-type-text',
 147+ 'survey-question-type-number',
 148+ 'survey-question-type-select',
 149+ 'survey-question-type-radio',
 150+ 'survey-question-type-textarea',
 151+ 'survey-question-type-check',
 152+ 'survey-question-label-nr',
 153+ 'survey-special-label-required',
 154+ 'survey-special-label-type',
 155+ 'survey-special-label-text',
 156+ 'survey-special-label-addquestion',
 157+ 'survey-special-label-add-first',
 158+ 'survey-special-label-add-another',
 159+ 'survey-special-remove',
 160+ 'survey-special-remove-confirm',
 161+ 'survey-special-label-answers'
 162+ )
 163+);
 164+
 165+$wgResourceModules['ext.survey.numeric'] = $moduleTemplate + array(
 166+ 'scripts' => array(
 167+ 'jquery.numeric.js'
 168+ )
 169+);
 170+
 171+$wgResourceModules['ext.survey.JSON'] = $moduleTemplate + array(
 172+ 'scripts' => array(
 173+ 'JSON.js'
 174+ )
 175+);
 176+
 177+$wgResourceModules['ext.survey.jquery'] = $moduleTemplate + array(
 178+ 'scripts' => array(
 179+ 'fancybox/jquery.fancybox-1.3.4.js',
 180+ 'jquery.survey.js'
 181+ ),
 182+ 'styles' => array(
 183+ 'jquery.survey.css',
 184+ 'fancybox/jquery.fancybox-1.3.4.css'
 185+ ),
 186+ 'dependencies' => array( 'ext.survey', 'jquery.ui.button', 'ext.survey.numeric', 'ext.survey.JSON' ),
 187+ 'messages' => array(
 188+ 'survey-jquery-submit',
 189+ 'survey-jquery-finish',
 190+ 'survey-jquery-load-failed',
 191+ )
 192+);
 193+
 194+$wgResourceModules['ext.survey.tag'] = $moduleTemplate + array(
 195+ 'scripts' => array(
 196+ 'ext.survey.tag.js'
 197+ ),
 198+ 'dependencies' => array( 'ext.survey.jquery', 'jquery.cookie' ),
 199+);
 200+
 201+unset( $moduleTemplate );
 202+
 203+$egSurveySettings = array();
Property changes on: tags/extensions/Survey/REL_0_1_2/Survey.php
___________________________________________________________________
Added: svn:eol-style
1204 + native
Index: tags/extensions/Survey/REL_0_1_2/Survey.sql
@@ -0,0 +1,47 @@
 2+-- MySQL version of the database schema for the Survey extension.
 3+-- Licence: GNU GPL v3+
 4+-- Author: Jeroen De Dauw < jeroendedauw@gmail.com >
 5+
 6+-- Surveys
 7+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/surveys (
 8+ survey_id SMALLINT unsigned NOT NULL auto_increment PRIMARY KEY,
 9+ survey_name VARCHAR(255) NOT NULL, -- String indentifier for the survey
 10+ survey_title VARCHAR(255) NOT NULL, -- Title of the survey
 11+ survey_enabled TINYINT NOT NULL default '0', -- If the survey can be taken by users
 12+ survey_header TEXT NOT NULL, -- Text to display above the survey
 13+ survey_footer TEXT NOT NULL, -- Text to display below the survey
 14+ survey_thanks TEXT NOT NULL, -- Text to display after survey submission
 15+ survey_user_type TINYINT unsigned NOT NULL default '0', -- Type of users that can participate in the survey
 16+ survey_namespaces BLOB NOT NULL, -- Namespaces on which the survey can be displayed
 17+ survey_ratio TINYINT unsigned NOT NULL, -- Percentage of users to show the survey to
 18+ survey_expiry INT unsigned NOT NULL, -- Coockie expiry time for the survey
 19+ survey_min_pages TINYINT unsigned NOT NULL -- Min amount of pages the user needs to view before getting the survey
 20+) /*$wgDBTableOptions*/;
 21+
 22+-- Questions
 23+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/survey_questions (
 24+ question_id INT(10) unsigned NOT NULL auto_increment PRIMARY KEY,
 25+ question_survey_id SMALLINT unsigned NOT NULL, -- Foreign key: surveys.survey_id
 26+ question_text TEXT NOT NULL,
 27+ question_type INT(2) unsigned NOT NULL,
 28+ question_required TINYINT NOT NULL,
 29+ question_answers BLOB NOT NULL,
 30+ question_removed TINYINT NOT NULL default '0'
 31+) /*$wgDBTableOptions*/;
 32+
 33+-- Submissions
 34+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/survey_submissions (
 35+ submission_id INT(10) unsigned NOT NULL auto_increment PRIMARY KEY,
 36+ submission_survey_id SMALLINT unsigned NOT NULL, -- Foreign key: surveys.survey_id
 37+ submission_user_name VARCHAR(255) NOT NULL, -- The person that made the submission (account name or ip)
 38+ submission_page_id INT(10) unsigned NULL, -- The id of the page the submission was made on
 39+ submission_time CHAR(14) binary NOT NULL default '' -- The time the submission was made
 40+) /*$wgDBTableOptions*/;
 41+
 42+-- Answers
 43+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/survey_answers (
 44+ answer_id SMALLINT unsigned NOT NULL auto_increment PRIMARY KEY,
 45+ answer_submission_id INT(10) unsigned NOT NULL, -- Foreign key: survey_submissions.submission_id
 46+ answer_question_id INT(10) unsigned NOT NULL, -- Foreign key: survey_questions.question_id
 47+ answer_text BLOB NOT NULL
 48+) /*$wgDBTableOptions*/;
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/Survey.sql
___________________________________________________________________
Added: svn:eol-style
149 + native
Index: tags/extensions/Survey/REL_0_1_2/README
@@ -0,0 +1,44 @@
 2+These is the readme file for the Survey extension.
 3+
 4+Extension page on mediawiki.org: http://www.mediawiki.org/wiki/Extension:Survey
 5+Latest version of the readme file: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Survey/README?view=co
 6+
 7+== About ==
 8+
 9+Survey is a MediaWiki extension that allows administrators to define surveys
 10+that can then be shown to specified groups of users.
 11+
 12+=== Feature overview ===
 13+
 14+* Surveys get displayed to wiki users using a nice pop-up form.
 15+* Surveys can be created and modified via an admin panel (Special:Surveys).
 16+* Surveys can be shown to specific types of users (logged in, anonymous, editor, confirmed, ...)
 17+* Surveys can be shown for a specified percentage of users, and only after a certain amount of page views.
 18+* Survey questions can have different types of inputs, of which some allow restricting answers.
 19+* Surveys can be tested by admins via Special:TakeSurvey without them being live on the wiki.
 20+* Summaries of survey submissions can be found on Special:SurveyStats.
 21+* The survey submission data (ie user answers) can be exported via an API.
 22+
 23+== Contributing ==
 24+
 25+If you have bug reports or requests, please add them to the Talk page:
 26+http://www.mediawiki.org/w/index.php?title=Extension_talk:Survey
 27+You can also send them to Jeroen De Dauw by email, jeroendedauw at googles mail service.
 28+
 29+For more info, see http://www.mediawiki.org/wiki/Extension:Survey
 30+
 31+== Credits to other projects ==
 32+
 33+* Fancybox
 34+This extension includes code from the FancyBox library. FancyBox is an open-source
 35+jQuery library dual licensed under the MIT [0] and GPL [1] licenses.
 36+
 37+* jquery.numeric
 38+This extension includes a copy of the jquery.numeric extension by Sam Collett.
 39+It's dual licensed under the MIT [0] and GPL [1] licenses.
 40+
 41+* JSON.js
 42+This extension icnludes a copy of JSON.js, which is in the public domain.
 43+
 44+[0] http://www.opensource.org/licenses/mit-license.php
 45+[1] http://www.opensource.org/licenses/gpl-license.php
Property changes on: tags/extensions/Survey/REL_0_1_2/README
___________________________________________________________________
Added: svn:eol-style
146 + native
Index: tags/extensions/Survey/REL_0_1_2/sql/Survey_indexSurveyName.sql
@@ -0,0 +1 @@
 2+CREATE UNIQUE INDEX /*i*/surveys_survey_name ON /*_*/surveys (survey_name);
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/sql/Survey_indexSurveyName.sql
___________________________________________________________________
Added: svn:eol-style
13 + native
Index: tags/extensions/Survey/REL_0_1_2/sql/Survey_indexQuestionId.sql
@@ -0,0 +1 @@
 2+CREATE INDEX /*i*/surveys_question_id ON /*_*/survey_answers (answer_question_id);
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/sql/Survey_indexQuestionId.sql
___________________________________________________________________
Added: svn:eol-style
13 + native
Index: tags/extensions/Survey/REL_0_1_2/sql/Survey_indexSubmissionId.sql
@@ -0,0 +1 @@
 2+CREATE INDEX /*i*/surveys_submission_id ON /*_*/survey_answers (answer_submission_id);
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/sql/Survey_indexSubmissionId.sql
___________________________________________________________________
Added: svn:eol-style
13 + native
Index: tags/extensions/Survey/REL_0_1_2/Survey.i18n.php
@@ -0,0 +1,1153 @@
 2+<?php
 3+
 4+/**
 5+ * Internationalization file for the Survey extension.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file Survey.i18n.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3+
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+
 16+$messages = array();
 17+
 18+/** English
 19+ * @author Jeroen De Dauw
 20+ */
 21+$messages['en'] = array(
 22+ 'survey-desc' => 'Survey tool for MediaWiki',
 23+
 24+ // Rights
 25+ 'right-surveyadmin' => 'Manage surveys',
 26+ 'right-surveysubmit' => 'Participate in surveys',
 27+
 28+ 'action-surveyadmin' => 'manage surveys',
 29+ 'action-surveysubmit' => 'participate in surveys',
 30+
 31+ // Groups
 32+ 'group-surveyadmin' => 'Survey admins',
 33+ 'group-surveyadmin-member' => '{{GENDER:$1|survey admin}}',
 34+ 'grouppage-surveyadmin' => 'Project:Survey_admins',
 35+
 36+ 'group-surveysubmit' => 'Survey participants',
 37+ 'group-surveysubmit-member' => '{{GENDER:$1|survey participant}}',
 38+ 'grouppage-surveysubmit' => 'Project:Survey_participants',
 39+
 40+ // Special page names
 41+ 'special-editsurvey' => 'Survey admin',
 42+ 'special-surveys' => 'Surveys admin',
 43+ 'special-surveystats' => 'Survey statistics',
 44+ 'special-takesurvey' => 'Take survey',
 45+
 46+ // API errors
 47+ 'survey-err-id-xor-name' => 'You need to provide either the ID or the name of the survey to submit',
 48+ 'survey-err-survey-name-unknown' => 'There is no survey with the name "$1"',
 49+ 'survey-err-duplicate-name' => 'There already is a survey with the name "$1"',
 50+ 'survey-err-ids-xor-names' => 'You need to provide either the IDs or the names of the surveys to query',
 51+
 52+ // Question types
 53+ 'survey-question-type-text' => 'Single-line text field',
 54+ 'survey-question-type-number' => 'Number',
 55+ 'survey-question-type-select' => 'Dropdown menu',
 56+ 'survey-question-type-radio' => 'Radio buttons',
 57+ 'survey-question-type-textarea' => 'Multi-line text field',
 58+ 'survey-question-type-check' => 'Checkbox',
 59+
 60+ // User types
 61+ 'survey-user-type-all' => 'Everyone',
 62+ 'survey-user-type-loggedin' => 'Logged in users',
 63+ 'survey-user-type-confirmed' => 'Confirmed users',
 64+ 'survey-user-type-editor' => 'Editors',
 65+ 'survey-user-type-anon' => 'Anonymous users',
 66+
 67+ // Navigation
 68+ 'survey-navigation-edit' => '[[Special:Survey/$1|Edit this survey]]',
 69+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|Take this survey]]',
 70+ 'survey-navigation-list' => '[[Special:Surveys|Surveys list]]',
 71+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|View statistics]]',
 72+
 73+ // Special:Surveys
 74+ 'surveys-special-addnew' => 'Add a new survey',
 75+ 'surveys-special-namedoc' => 'Enter an unique identifier (ID) for the new survey. Can not be changed later. For example: editor-motivation.',
 76+ 'surveys-special-newname' => 'New survey ID:',
 77+ 'surveys-special-add' => 'Add survey',
 78+ 'surveys-special-existing' => 'Existing surveys',
 79+ 'surveys-special-title' => 'Title',
 80+ 'surveys-special-status' => 'Status',
 81+ 'surveys-special-stats' => 'Statistics',
 82+ 'surveys-special-edit' => 'Edit',
 83+ 'surveys-special-save' => 'Save',
 84+ 'surveys-special-delete' => 'Delete',
 85+ 'surveys-special-enabled' => 'Enabled',
 86+ 'surveys-special-disabled' => 'Disabled',
 87+ 'surveys-special-confirm-delete' => 'Are you sure you want to delete this survey?',
 88+ 'surveys-special-delete-failed' => 'Failed to delete survey.',
 89+ 'survey-special-label-usertype' => 'Users that should get the survey',
 90+ 'survey-special-label-minpages' => 'Minimun amount of pages the user needs to visit before getting the survey',
 91+
 92+ // Special:TakeSurvey
 93+ 'surveys-takesurvey-loading' => 'Loading survey...',
 94+ 'surveys-takesurvey-nosuchsurvey' => 'The requested survey does not exist.',
 95+ 'surveys-takesurvey-warn-notenabled' => 'This survey has not been enabled yet, and therefore is not visible to users.',
 96+ 'surveys-takesurvey-surveynotenabled' => 'The requested survey has not been enabled yet.',
 97+
 98+ // Special:SurveyStats
 99+ 'surveys-surveystats-nosuchsurvey' => 'The requested survey does not exist. You can view a [[Special:Surveys|list of available surveys]].',
 100+ 'surveys-surveystats-name' => 'Survey ID',
 101+ 'surveys-surveystats-title' => 'Survey title',
 102+ 'surveys-surveystats-status' => 'Survey status',
 103+ 'surveys-surveystats-questioncount' => 'Number of questions',
 104+ 'surveys-surveystats-submissioncount' => 'Number of submissions',
 105+ 'surveys-surveystats-enabled' => 'Enabled',
 106+ 'surveys-surveystats-disabled' => 'Disabled',
 107+ 'surveys-surveystats-questions' => 'Question statistics',
 108+ 'surveys-surveystats-question-nr' => '#',
 109+ 'surveys-surveystats-question-#' => '$1',
 110+ 'surveys-surveystats-question-type' => 'Question type',
 111+ 'surveys-surveystats-question-text' => 'Question text',
 112+ 'surveys-surveystats-question-answercount' => 'Number of answers',
 113+ 'surveys-surveystats-question-answers' => 'Most provided answers',
 114+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|answer|answers}})',
 115+ 'surveys-surveystats-unchecked' => 'Unchecked',
 116+ 'surveys-surveystats-checked' => 'Checked',
 117+
 118+ // Special:Survey
 119+ 'surveys-special-unknown-name' => 'There is no survey with the requested ID.',
 120+ 'survey-special-label-name' => 'Survey ID',
 121+ 'survey-special-label-title' => 'Survey title',
 122+ 'survey-special-label-enabled' => 'Survey enabled',
 123+ 'survey-special-label-ratio' => 'Percentage of people to show the survey to',
 124+ 'survey-special-label-add-first' => 'Add question',
 125+ 'survey-special-label-add-another' => 'Add another question',
 126+ 'survey-special-label-addquestion' => 'New question',
 127+ 'survey-question-label-nr' => 'Question #$1',
 128+ 'survey-special-label-required' => 'Question is required',
 129+ 'survey-special-label-type' => 'Question type',
 130+ 'survey-special-label-text' => 'Question text',
 131+ 'survey-special-remove' => 'Remove question',
 132+ 'survey-special-remove-confirm' => 'Are you sure you want to remove this question?',
 133+ 'survey-special-label-header' => 'Text to display above the survey',
 134+ 'survey-special-label-footer' => 'Text to display below the survey',
 135+ 'survey-special-label-thanks' => 'Thanks message to display after submission of the survey',
 136+ 'survey-special-label-answers' => 'Available answers, one per line.',
 137+
 138+ // Survey jQuery
 139+ 'survey-jquery-submit' => 'Submit',
 140+ 'survey-jquery-finish' => 'Finish',
 141+ 'survey-jquery-load-failed' => 'Could not load the survey.',
 142+);
 143+
 144+/** Message documentation (Message documentation)
 145+ * @author Jeroen De Dauw
 146+ * @author Kghbln
 147+ * @author SPQRobin
 148+ * @author Siebrand
 149+ * @author Umherirrender
 150+ */
 151+$messages['qqq'] = array(
 152+ 'right-surveyadmin' => '{{doc-right|surveyadmin}}',
 153+ 'right-surveysubmit' => '{{doc-right|surveysubmit}}',
 154+ 'group-surveyadmin' => '{{doc-group|surveyadmin}}',
 155+ 'group-surveyadmin-member' => '{{doc-group|surveyadmin|member}}',
 156+ 'grouppage-surveyadmin' => '{{doc-group|surveyadmin|page}}',
 157+ 'group-surveysubmit' => '{{doc-group|surveysubmit}}',
 158+ 'group-surveysubmit-member' => '{{doc-group|surveysubmit|member}}',
 159+ 'grouppage-surveysubmit' => '{{doc-group|surveysubmit|page}}',
 160+ 'special-editsurvey' => 'Special page name/title - shows on specified survery to edit',
 161+ 'special-surveys' => 'Special page name/title',
 162+ 'special-surveystats' => 'Special page name/title - shows statistics for one specified survey',
 163+ 'special-takesurvey' => 'Special page name/title',
 164+ 'survey-err-id-xor-name' => 'API error message.',
 165+ 'survey-err-survey-name-unknown' => 'API error message. Parameters:
 166+* $1 is the name of a survey.',
 167+ 'survey-err-duplicate-name' => 'API error message. $1 is the name of a survey.',
 168+ 'survey-err-ids-xor-names' => 'API error message.',
 169+ 'survey-question-type-text' => 'Input type for a question, selectable in administration interface.',
 170+ 'survey-question-type-number' => 'Input type for a question, selectable in administration interface.',
 171+ 'survey-question-type-select' => 'Input type for a question, selectable in administration interface.',
 172+ 'survey-question-type-radio' => 'Input type for a question, selectable in administration interface.',
 173+ 'survey-question-type-textarea' => 'Input type for a question, selectable in administration interface.',
 174+ 'survey-question-type-check' => 'Input type for a question, selectable in administration interface.',
 175+ 'survey-user-type-all' => 'Group of users for which a survey can be available.',
 176+ 'survey-user-type-loggedin' => 'Group of users for which a survey can be available.',
 177+ 'survey-user-type-confirmed' => 'Group of users for which a survey can be available.',
 178+ 'survey-user-type-editor' => 'Group of users for which a survey can be available.',
 179+ 'survey-user-type-anon' => 'Group of users for which a survey can be available.',
 180+ 'surveys-special-namedoc' => '[[File:Survey-surveys.png|300px]]',
 181+ 'surveys-surveystats-question-answers' => 'Header for a column listing the most provided answers per question',
 182+ 'surveys-surveystats-question-answer' => 'Header for a column listing the amount of answers per question',
 183+);
 184+
 185+/** Afrikaans (Afrikaans)
 186+ * @author Naudefj
 187+ */
 188+$messages['af'] = array(
 189+ 'survey-question-type-number' => 'Getal',
 190+ 'survey-user-type-all' => 'Almal',
 191+ 'survey-user-type-loggedin' => 'Aangemelde gebruikers',
 192+ 'survey-user-type-confirmed' => 'Bevestigde gebruikers',
 193+ 'survey-user-type-anon' => 'Anonieme gebruikers',
 194+ 'surveys-special-title' => 'Naam',
 195+ 'surveys-special-status' => 'Status',
 196+ 'surveys-special-stats' => 'Statistieke',
 197+ 'surveys-special-edit' => 'Wysig',
 198+ 'surveys-special-save' => 'Stoor',
 199+ 'surveys-special-delete' => 'Skrap',
 200+ 'surveys-special-enabled' => 'Aangeskakel',
 201+ 'surveys-special-disabled' => 'Afgeskakel',
 202+ 'surveys-surveystats-enabled' => 'Aangeskakel',
 203+ 'surveys-surveystats-disabled' => 'Afgeskakel',
 204+ 'surveys-surveystats-questions' => 'Vraagstatistieke',
 205+ 'surveys-surveystats-question-type' => 'Tipe vraag',
 206+ 'surveys-surveystats-question-text' => 'Vraagteks',
 207+ 'surveys-surveystats-question-answercount' => 'Aantal antwoorde',
 208+ 'surveys-surveystats-question-answers' => 'Mees gegewe antwoorde',
 209+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|antwoord|antwoorde}})',
 210+ 'survey-jquery-submit' => 'Dien in',
 211+ 'survey-jquery-finish' => 'Voltooi',
 212+);
 213+
 214+/** Arabic (العربية)
 215+ * @author روخو
 216+ */
 217+$messages['ar'] = array(
 218+ 'survey-question-type-number' => 'رقم',
 219+ 'survey-user-type-all' => 'الجميع',
 220+ 'survey-user-type-editor' => 'محررون',
 221+ 'surveys-special-addnew' => 'إضافة استطلاع جديد',
 222+ 'surveys-special-title' => 'العنوان',
 223+ 'surveys-special-status' => 'الحالة',
 224+ 'surveys-special-stats' => 'إحصاءات',
 225+ 'surveys-special-save' => 'احفظ',
 226+ 'surveys-special-delete' => 'احذف',
 227+ 'surveys-special-enabled' => 'مُفعّل',
 228+ 'surveys-special-disabled' => 'معطل',
 229+ 'surveys-special-confirm-delete' => 'هل أنت متأكد أنك تريد حذف هذا الاستطلاع؟',
 230+ 'surveys-special-delete-failed' => 'فشل في حذف الاستطلاع.',
 231+ 'surveys-surveystats-enabled' => 'مُفعّل',
 232+ 'surveys-surveystats-disabled' => 'معطل',
 233+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|إجابة|إجابات}})',
 234+ 'surveys-surveystats-unchecked' => 'غير مفحوصة',
 235+ 'surveys-surveystats-checked' => 'مفحوصة',
 236+ 'survey-special-label-add-first' => 'اضف سؤال',
 237+ 'survey-special-label-add-another' => 'اضف سؤال اخر',
 238+ 'survey-special-label-addquestion' => 'سؤال جديد',
 239+ 'survey-special-label-type' => 'نمط السؤال',
 240+ 'survey-special-label-text' => 'نص السؤال',
 241+ 'survey-special-remove' => 'حذف السؤال',
 242+ 'survey-jquery-submit' => 'أرسل',
 243+ 'survey-jquery-finish' => 'أنهي',
 244+);
 245+
 246+/** Breton (Brezhoneg)
 247+ * @author Fulup
 248+ * @author Y-M D
 249+ */
 250+$messages['br'] = array(
 251+ 'survey-desc' => 'Ostilh sontadegoù evit MediaWiki',
 252+ 'right-surveyadmin' => 'Merañ sontadegoù',
 253+ 'right-surveysubmit' => 'Kemer perzh er sontadegoù',
 254+ 'survey-question-type-number' => 'Niver',
 255+ 'survey-question-type-select' => 'Lañser desachañ',
 256+ 'survey-question-type-check' => 'Log da askañ',
 257+ 'survey-user-type-all' => 'An holl',
 258+ 'survey-user-type-loggedin' => 'Implijerien kevreet',
 259+ 'survey-user-type-confirmed' => 'Implijerien kadarnaet',
 260+ 'survey-user-type-editor' => 'Skridaozerien',
 261+ 'survey-user-type-anon' => 'Implijerien dizanv',
 262+ 'survey-navigation-edit' => '[[Special:Survey/$1|Kemmañ ar sontadeg-mañ]]',
 263+ 'survey-navigation-list' => '[[Special:Surveys|Roll ar sontadegoù]]',
 264+ 'surveys-special-addnew' => 'Ouzhpennañ ur sontadeg nevez',
 265+ 'surveys-special-add' => 'Ouzhpennañ ur sontadeg',
 266+ 'surveys-special-existing' => 'Ar sontadegoù a zo diouto',
 267+ 'surveys-special-title' => 'Titl',
 268+ 'surveys-special-status' => 'Statud',
 269+ 'surveys-special-stats' => 'Stadegoù',
 270+ 'surveys-special-edit' => 'Aozañ',
 271+ 'surveys-special-save' => 'Enrollañ',
 272+ 'surveys-special-delete' => 'Diverkañ',
 273+ 'surveys-special-enabled' => 'Gweredekaet',
 274+ 'surveys-special-disabled' => 'Diweredekaet',
 275+ 'surveys-takesurvey-loading' => 'O kargañ ar sontadeg...',
 276+ 'surveys-surveystats-name' => 'ID ar sontadeg',
 277+ 'surveys-surveystats-title' => 'Titl ar sontadeg',
 278+ 'surveys-surveystats-status' => 'Statud ar sontadeg',
 279+ 'surveys-surveystats-questioncount' => "Niver a c'houlennoù",
 280+ 'surveys-surveystats-submissioncount' => 'Niver a respontoù',
 281+ 'surveys-surveystats-enabled' => 'Gweredekaet',
 282+ 'surveys-surveystats-disabled' => 'Diweredekaet',
 283+ 'surveys-surveystats-questions' => 'Stadegoù ar goulennoù',
 284+ 'surveys-surveystats-question-answercount' => 'Niver a respontoù',
 285+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|respont|respont}})',
 286+ 'surveys-surveystats-unchecked' => 'Nann-gwiriet',
 287+ 'surveys-surveystats-checked' => 'Gwiriet',
 288+ 'survey-special-label-name' => 'ID ar sontadeg',
 289+ 'survey-special-label-title' => 'Titl ar sontadeg',
 290+ 'survey-special-label-add-first' => 'Ouzhpennañ ur goulenn',
 291+ 'survey-special-label-add-another' => 'Ouzhpennañ ur goulenn all',
 292+ 'survey-special-label-addquestion' => 'Goulenn nevez',
 293+ 'survey-question-label-nr' => 'Goulenn #$1',
 294+ 'survey-special-remove' => 'Lemel kuit at goulenn',
 295+ 'survey-jquery-submit' => 'Kas',
 296+ 'survey-jquery-finish' => 'Echuiñ',
 297+);
 298+
 299+/** German (Deutsch)
 300+ * @author Kghbln
 301+ */
 302+$messages['de'] = array(
 303+ 'survey-desc' => 'Ermöglicht Umfragen',
 304+ 'right-surveyadmin' => 'Umfragen verwalten',
 305+ 'right-surveysubmit' => 'An Umfragen teilnehmen',
 306+ 'group-surveyadmin' => 'Umfrageadministratoren',
 307+ 'group-surveyadmin-member' => '{{GENDER:$1|Umfrageadministrator|Umfrageadministratorin}}',
 308+ 'grouppage-surveyadmin' => 'Project:Umfrageadministratoren',
 309+ 'group-surveysubmit' => 'Umfrageteilnehmer',
 310+ 'group-surveysubmit-member' => '{{GENDER:$1|Umfrageteilnehmer|Umfrageteilnehmerin}}',
 311+ 'grouppage-surveysubmit' => 'Project:Umfrageteilnehmer',
 312+ 'special-editsurvey' => 'Umfrageverwaltung',
 313+ 'special-surveys' => 'Umfragenliste',
 314+ 'special-surveystats' => 'Umfragestatistiken',
 315+ 'special-takesurvey' => 'An der Umfrage teilnehmen',
 316+ 'survey-err-id-xor-name' => 'Es muss entweder die Kennung oder der Name der Umfrage angegeben werden, um die Umfrage speichern zu können.',
 317+ 'survey-err-survey-name-unknown' => 'Es ist keine Umfrage mit dem Namen „$1“ vorhanden.',
 318+ 'survey-err-duplicate-name' => 'Es ist bereits eine Umfrage mit dem Namen „$1“ vorhanden.',
 319+ 'survey-err-ids-xor-names' => 'Es müssen entweder die Kennungen oder die Namen der Umfragen angegeben werden, die abgefragt werden sollen.',
 320+ 'survey-question-type-text' => 'Einzeiliges Textfeld',
 321+ 'survey-question-type-number' => 'Nummernfeld',
 322+ 'survey-question-type-select' => 'Ausklappmenü',
 323+ 'survey-question-type-radio' => 'Optionsfeld',
 324+ 'survey-question-type-textarea' => 'Mehrzeiliges Textfeld',
 325+ 'survey-question-type-check' => 'Ankreuzfeld',
 326+ 'survey-user-type-all' => 'Jeder',
 327+ 'survey-user-type-loggedin' => 'Angemeldete Benutzer',
 328+ 'survey-user-type-confirmed' => 'Bestätigte Benutzer',
 329+ 'survey-user-type-editor' => 'Sichter',
 330+ 'survey-user-type-anon' => 'Unangemeldete Benutzer',
 331+ 'survey-navigation-edit' => '[[Special:Survey/$1|Diese Umfrage bearbeiten]]',
 332+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|An dieser Umfragen teilnehmen]]',
 333+ 'survey-navigation-list' => '[[Special:Surveys|Umfragenliste]]',
 334+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|Umfragestatistiken ansehen]]',
 335+ 'surveys-special-addnew' => 'Eine neue Umfrage hinzufügen',
 336+ 'surveys-special-namedoc' => 'Gib eine eindeutige Kennung für die neue Umfrage an, z. B. Bearbeitermotivation. Sie kann später nicht mehr verändert werden.',
 337+ 'surveys-special-newname' => 'Die neue Umfragekennung:',
 338+ 'surveys-special-add' => 'Umfrage hinzufügen',
 339+ 'surveys-special-existing' => 'Vorhanden Umfragen',
 340+ 'surveys-special-title' => 'Bezeichnung',
 341+ 'surveys-special-status' => 'Status',
 342+ 'surveys-special-stats' => 'Statistiken',
 343+ 'surveys-special-edit' => 'Bearbeiten',
 344+ 'surveys-special-save' => 'Speichern',
 345+ 'surveys-special-delete' => 'Löschen',
 346+ 'surveys-special-enabled' => 'Aktiviert',
 347+ 'surveys-special-disabled' => 'Deaktiviert',
 348+ 'surveys-special-confirm-delete' => 'Soll diese Umfrage tatsächlich gelöscht werden?',
 349+ 'surveys-special-delete-failed' => 'Die Umfrage konnte nicht gelöscht werden.',
 350+ 'survey-special-label-usertype' => 'Benutzer, denen die Umfrage angezeigt werden soll',
 351+ 'survey-special-label-minpages' => 'Die Mindestanzahl an Seiten, die ein Benutzer aufgerufen haben muss, bevor er die Umfrage angezeigt bekommt.',
 352+ 'surveys-takesurvey-loading' => 'Die Umfrage wird geladen …',
 353+ 'surveys-takesurvey-nosuchsurvey' => 'Die angeforderte Umfrage ist nicht vorhanden.',
 354+ 'surveys-takesurvey-warn-notenabled' => 'Diese Umfrage wurde bislang noch nicht aktiviert, und ist daher noch nicht für Benutzer sichtbar.',
 355+ 'surveys-takesurvey-surveynotenabled' => 'Die angeforderte Studie wurde bislang noch nicht aktiviert.',
 356+ 'surveys-surveystats-nosuchsurvey' => 'Die angeforderte Umfrage ist nicht vorhanden. Eine Liste der verfügbaren Umfragen befindet sich auf der Seite [[Special:Surveys]].',
 357+ 'surveys-surveystats-name' => 'Umfragekennung',
 358+ 'surveys-surveystats-title' => 'Umfragebezeichnung',
 359+ 'surveys-surveystats-status' => 'Umfragestatus',
 360+ 'surveys-surveystats-questioncount' => 'Anzahl der Fragen',
 361+ 'surveys-surveystats-submissioncount' => 'Anzahl der Teilnahmen',
 362+ 'surveys-surveystats-enabled' => 'Aktiviert',
 363+ 'surveys-surveystats-disabled' => 'Deaktiviert',
 364+ 'surveys-surveystats-questions' => 'Fragestatistiken',
 365+ 'surveys-surveystats-question-type' => 'Fragentyp',
 366+ 'surveys-surveystats-question-text' => 'Text der Frage',
 367+ 'surveys-surveystats-question-answercount' => 'Anzahl der Antworten',
 368+ 'surveys-surveystats-question-answers' => 'Die am meisten gegebenen Antworten',
 369+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|Antwort|Antworten}})',
 370+ 'surveys-surveystats-unchecked' => 'Nicht geprüft',
 371+ 'surveys-surveystats-checked' => 'Geprüft',
 372+ 'surveys-special-unknown-name' => 'Zur angeforderten Kennung ist keine Umfrage vorhanden.',
 373+ 'survey-special-label-name' => 'Umfragekennung',
 374+ 'survey-special-label-title' => 'Umfragebezeichnung',
 375+ 'survey-special-label-enabled' => 'Umfrage aktiviert',
 376+ 'survey-special-label-ratio' => 'Prozentsatz der Personen, denen diese Umfrage angezeigt werden soll',
 377+ 'survey-special-label-add-first' => 'Frage hinzufügen',
 378+ 'survey-special-label-add-another' => 'Eine weitere Frage hinzufügen',
 379+ 'survey-special-label-addquestion' => 'Neue Frage',
 380+ 'survey-question-label-nr' => 'Frage $1',
 381+ 'survey-special-label-required' => 'Die Beantwortung dieser Frage ist erforderlich.',
 382+ 'survey-special-label-type' => 'Fragetyp',
 383+ 'survey-special-label-text' => 'Text der Frage',
 384+ 'survey-special-remove' => 'Frage entfernen',
 385+ 'survey-special-remove-confirm' => 'Soll diese Frage tatsächlich entfernt werden?',
 386+ 'survey-special-label-header' => 'Der oberhalb der Umfrage anzuzeigende Text',
 387+ 'survey-special-label-footer' => 'Der unterhalb der Umfrage anzuzeigende Text',
 388+ 'survey-special-label-thanks' => 'Die Dankesnachricht, die nach Abschluss der Teilnahme angezeigt werden soll',
 389+ 'survey-special-label-answers' => 'Verfügbare Antworten (eine pro Zeile)',
 390+ 'survey-jquery-submit' => 'Absenden',
 391+ 'survey-jquery-finish' => 'Beenden',
 392+ 'survey-jquery-load-failed' => 'Die Umfrage konnte nicht geladen werden.',
 393+);
 394+
 395+/** German (formal address) (‪Deutsch (Sie-Form)‬)
 396+ * @author Kghbln
 397+ */
 398+$messages['de-formal'] = array(
 399+ 'surveys-special-namedoc' => 'Geben Sie eine eindeutige Kennung für die neue Umfrage an, z. B. Bearbeitermotivation. Sie kann später nicht mehr verändert werden.',
 400+);
 401+
 402+/** French (Français)
 403+ * @author Gomoko
 404+ * @author Tpt
 405+ */
 406+$messages['fr'] = array(
 407+ 'survey-desc' => 'Outil de sondage pour MediaWiki',
 408+ 'right-surveyadmin' => 'Gérer les sondages',
 409+ 'right-surveysubmit' => 'Participer aux sondages',
 410+ 'group-surveyadmin' => 'Administrateurs de sondage',
 411+ 'group-surveyadmin-member' => '{{GENDER:$1|administrateur de sondage}}',
 412+ 'grouppage-surveyadmin' => 'Project:Survey_admins',
 413+ 'group-surveysubmit' => 'Participants au sondage',
 414+ 'group-surveysubmit-member' => '{{GENDER:$1|participant au sondage}}',
 415+ 'grouppage-surveysubmit' => 'Project:Survey_participants',
 416+ 'special-editsurvey' => 'Administrateur de sondage',
 417+ 'special-surveys' => 'Administrateur des sondages',
 418+ 'special-surveystats' => 'Statistiques des sondages',
 419+ 'special-takesurvey' => 'Prendre le sondage',
 420+ 'survey-err-id-xor-name' => "Vous devez fournir soit l'ID soit le nom du sondage à soumettre",
 421+ 'survey-err-survey-name-unknown' => 'Il n\'y a pas de sondage avec le nom "$1"',
 422+ 'survey-err-duplicate-name' => 'Il y a déjà un sondage avec le nom "$1"',
 423+ 'survey-err-ids-xor-names' => 'Vous devez fournit soit les IDs soit les noms des sondages à demander',
 424+ 'survey-question-type-text' => 'Champ de texte mono-ligne',
 425+ 'survey-question-type-number' => 'Nombre',
 426+ 'survey-question-type-select' => 'Menu déroulant',
 427+ 'survey-question-type-radio' => 'Boutons radio',
 428+ 'survey-question-type-textarea' => 'Champ de texte multi-lignes',
 429+ 'survey-question-type-check' => 'Case à cocher',
 430+ 'survey-user-type-all' => 'Tout le monde',
 431+ 'survey-user-type-loggedin' => 'Utilisateurs connectés',
 432+ 'survey-user-type-confirmed' => 'Utilisateurs confirmés',
 433+ 'survey-user-type-editor' => 'Contributeurs',
 434+ 'survey-user-type-anon' => 'Utilisateurs anonymes',
 435+ 'survey-navigation-edit' => '[[Special:Survey/$1|Modifier ce sondage]]',
 436+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|Participer à ce sondage]]',
 437+ 'survey-navigation-list' => '[[Special:Surveys|Liste des sondages]]',
 438+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|Voir les statistiques]]',
 439+ 'surveys-special-addnew' => 'Ajouter un nouveau sondage',
 440+ 'surveys-special-namedoc' => 'Entrez un identifiant (ID) unique pour le nouveau sondage. Il ne peut pas être changé ultérieurement. Par exemple: motivation-contributeur.',
 441+ 'surveys-special-newname' => 'Nouvel ID du sondage:',
 442+ 'surveys-special-add' => 'Ajouter un sondage',
 443+ 'surveys-special-existing' => 'Sondages existants',
 444+ 'surveys-special-title' => 'Titre',
 445+ 'surveys-special-status' => 'Statut',
 446+ 'surveys-special-stats' => 'Statistiques',
 447+ 'surveys-special-edit' => 'Modifier',
 448+ 'surveys-special-save' => 'Enregistrer',
 449+ 'surveys-special-delete' => 'Supprimer',
 450+ 'surveys-special-enabled' => 'Activé',
 451+ 'surveys-special-disabled' => 'Désactivé',
 452+ 'surveys-special-confirm-delete' => 'Êtes-vous sûrs de vouloir supprimer ce sondage?',
 453+ 'surveys-special-delete-failed' => 'Échec de la suppression du sondage.',
 454+ 'survey-special-label-usertype' => 'Utilisateurs qui devraient obtenir le sondage',
 455+ 'survey-special-label-minpages' => "Nombre minimal de pages que l'utilisateur doit avoir vues avant d'obtenir le sondage",
 456+ 'surveys-takesurvey-loading' => 'Chargement du sondage...',
 457+ 'surveys-takesurvey-nosuchsurvey' => "Le sondage demandé n'existe pas.",
 458+ 'surveys-takesurvey-warn-notenabled' => "Ce sondage n'a pas encore été activé, et n'est donc pas visible pour les utilisateurs.",
 459+ 'surveys-takesurvey-surveynotenabled' => "Le sondage demandé n'a pas encore été activé.",
 460+ 'surveys-surveystats-nosuchsurvey' => "Le sondage demandé n'existe pas. Vous pouvez afficher une [[Special:Surveys|liste des sondages disponibles]].",
 461+ 'surveys-surveystats-name' => 'ID du sondage',
 462+ 'surveys-surveystats-title' => 'Titre du sondage',
 463+ 'surveys-surveystats-status' => 'Statut du sondage',
 464+ 'surveys-surveystats-questioncount' => 'Nombre de questions',
 465+ 'surveys-surveystats-submissioncount' => 'Nombre de réponses',
 466+ 'surveys-surveystats-enabled' => 'Activé',
 467+ 'surveys-surveystats-disabled' => 'Désactivé',
 468+ 'surveys-surveystats-questions' => 'Statistiques des questions',
 469+ 'surveys-surveystats-question-type' => 'Type de question',
 470+ 'surveys-surveystats-question-text' => 'Texte de la question',
 471+ 'surveys-surveystats-question-answercount' => 'Nombre de réponses',
 472+ 'surveys-surveystats-question-answers' => 'Réponses les plus fréquentes',
 473+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|réponse|réponses}})',
 474+ 'surveys-surveystats-unchecked' => 'Non coché',
 475+ 'surveys-surveystats-checked' => 'Coché',
 476+ 'surveys-special-unknown-name' => "Il n'y a pas de sondage avec l'ID demandé.",
 477+ 'survey-special-label-name' => 'ID du sondage',
 478+ 'survey-special-label-title' => 'Titre du sondage',
 479+ 'survey-special-label-enabled' => 'Sondage activé',
 480+ 'survey-special-label-ratio' => 'Pourcentage de personnes à qui afficher le sondage',
 481+ 'survey-special-label-add-first' => 'Ajouter une question',
 482+ 'survey-special-label-add-another' => 'Ajouter une autre question',
 483+ 'survey-special-label-addquestion' => 'Nouvelle question',
 484+ 'survey-question-label-nr' => 'Question #$1',
 485+ 'survey-special-label-required' => 'Une question est obligatoire',
 486+ 'survey-special-label-type' => 'Type de question',
 487+ 'survey-special-label-text' => 'Texte de la question',
 488+ 'survey-special-remove' => 'Supprimer la question',
 489+ 'survey-special-remove-confirm' => 'Êtes-vous sûrs de vouloir supprimer cette question?',
 490+ 'survey-special-label-header' => 'Texte à afficher au-dessus du sondage',
 491+ 'survey-special-label-footer' => 'Texte à afficher en-dessous du sondage',
 492+ 'survey-special-label-thanks' => "Message de remerciement à afficher après l'envoi du sondage",
 493+ 'survey-special-label-answers' => 'Réponses possibles, une par ligne.',
 494+ 'survey-jquery-submit' => 'Envoyer',
 495+ 'survey-jquery-finish' => 'Terminer',
 496+ 'survey-jquery-load-failed' => 'Impossible de charger le sondage.',
 497+);
 498+
 499+/** Franco-Provençal (Arpetan)
 500+ * @author ChrisPtDe
 501+ */
 502+$messages['frp'] = array(
 503+ 'survey-desc' => 'Outil de sondâjo por MediaWiki',
 504+ 'right-surveyadmin' => 'Administrar los sondâjos',
 505+ 'right-surveysubmit' => 'Participar ux sondâjos',
 506+ 'group-surveyadmin' => 'Administrators de sondâjo',
 507+ 'group-surveyadmin-member' => 'administrat{{GENDER:$1|or|rice}} de sondâjo',
 508+ 'grouppage-surveyadmin' => 'Project:Administrators_de_sondâjo',
 509+ 'group-surveysubmit' => 'Participents u sondâjo',
 510+ 'group-surveysubmit-member' => 'participent{{GENDER:$1||a}} u sondâjo',
 511+ 'grouppage-surveysubmit' => 'Project:Participents_u_sondâjo',
 512+ 'special-editsurvey' => 'Administrator de sondâjo',
 513+ 'special-surveys' => 'Administrator des sondâjos',
 514+ 'special-surveystats' => 'Statistiques des sondâjos',
 515+ 'special-takesurvey' => 'Prendre lo sondâjo',
 516+ 'survey-question-type-number' => 'Numerô',
 517+ 'survey-question-type-radio' => 'Botons radiô',
 518+ 'survey-question-type-check' => 'Câsa a pouentar',
 519+ 'survey-user-type-all' => 'Tot lo mondo',
 520+ 'survey-user-type-loggedin' => 'Utilisators branchiês',
 521+ 'survey-user-type-confirmed' => 'Utilisators confirmâs',
 522+ 'survey-user-type-editor' => 'Contributors',
 523+ 'survey-user-type-anon' => 'Utilisators pas encartâs',
 524+ 'survey-navigation-edit' => '[[Special:Survey/$1|Changiér cél sondâjo]]',
 525+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|Participar a cél sondâjo]]',
 526+ 'survey-navigation-list' => '[[Special:Surveys|Lista des sondâjos]]',
 527+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|Vêre les statistiques]]',
 528+ 'surveys-special-addnew' => 'Apondre un sondâjo novél',
 529+ 'surveys-special-newname' => 'Numerô novél du sondâjo :',
 530+ 'surveys-special-add' => 'Apondre un sondâjo',
 531+ 'surveys-special-existing' => 'Sondâjos ègzistents',
 532+ 'surveys-special-title' => 'Titro',
 533+ 'surveys-special-status' => 'Statut',
 534+ 'surveys-special-stats' => 'Statistiques',
 535+ 'surveys-special-edit' => 'Changiér',
 536+ 'surveys-special-save' => 'Encartar',
 537+ 'surveys-special-delete' => 'Suprimar',
 538+ 'surveys-special-enabled' => 'Activâ',
 539+ 'surveys-special-disabled' => 'Dèsactivâ',
 540+ 'surveys-takesurvey-loading' => 'Chargement du sondâjo...',
 541+ 'surveys-surveystats-name' => 'Numerô du sondâjo',
 542+ 'surveys-surveystats-title' => 'Titro du sondâjo',
 543+ 'surveys-surveystats-status' => 'Statut du sondâjo',
 544+ 'surveys-surveystats-questioncount' => 'Nombro de quèstions',
 545+ 'surveys-surveystats-submissioncount' => 'Nombro de somissions',
 546+ 'surveys-surveystats-enabled' => 'Activâ',
 547+ 'surveys-surveystats-disabled' => 'Dèsactivâ',
 548+ 'surveys-surveystats-questions' => 'Statistiques de les quèstions',
 549+ 'surveys-surveystats-question-type' => 'Tipo de quèstion',
 550+ 'surveys-surveystats-question-text' => 'Tèxto de la quèstion',
 551+ 'surveys-surveystats-question-answercount' => 'Nombro de rèponses',
 552+ 'surveys-surveystats-question-answer' => '$1 ($2 rèpons{{PLURAL:$2|a|es}})',
 553+ 'surveys-surveystats-unchecked' => 'Pas controlâ',
 554+ 'surveys-surveystats-checked' => 'Controlâ',
 555+ 'survey-special-label-name' => 'Numerô du sondâjo',
 556+ 'survey-special-label-title' => 'Titro du sondâjo',
 557+ 'survey-special-label-enabled' => 'Sondâjo activâ',
 558+ 'survey-special-label-add-first' => 'Apondre una quèstion',
 559+ 'survey-special-label-add-another' => 'Apondre una ôtra quèstion',
 560+ 'survey-special-label-addquestion' => 'Novèla quèstion',
 561+ 'survey-question-label-nr' => 'Quèstion numerô $1',
 562+ 'survey-special-label-required' => 'Una quèstion est oblegatouèra',
 563+ 'survey-special-label-type' => 'Tipo de quèstion',
 564+ 'survey-special-label-text' => 'Tèxto de la quèstion',
 565+ 'survey-special-remove' => 'Enlevar la quèstion',
 566+ 'survey-jquery-submit' => 'Sometre',
 567+ 'survey-jquery-finish' => 'Chavonar',
 568+);
 569+
 570+/** Galician (Galego)
 571+ * @author Toliño
 572+ */
 573+$messages['gl'] = array(
 574+ 'survey-desc' => 'Ferramenta de enquisa para MediaWiki',
 575+ 'right-surveyadmin' => 'Xestionar enquisas',
 576+ 'right-surveysubmit' => 'Participar en enquisas',
 577+ 'group-surveyadmin' => 'Administradores da enquisa',
 578+ 'group-surveyadmin-member' => '{{GENDER:$1|administrador da enquisa|administradora da enquisa}}',
 579+ 'grouppage-surveyadmin' => 'Project:Administradores da enquisa',
 580+ 'group-surveysubmit' => 'Participantes da enquisa',
 581+ 'group-surveysubmit-member' => '{{GENDER:$1|participante da enquisa}}',
 582+ 'grouppage-surveysubmit' => 'Project:Participantes da enquisa',
 583+ 'special-editsurvey' => 'Administración da enquisa',
 584+ 'special-surveys' => 'Administración das enquisas',
 585+ 'special-surveystats' => 'Estatísticas da enquisa',
 586+ 'special-takesurvey' => 'Completar a enquisa',
 587+ 'survey-err-id-xor-name' => 'Cómpre dar ou ben o ID ou ben o nome da enquisa para facer o envío',
 588+ 'survey-err-survey-name-unknown' => 'Non existe ningunha enquisa chamada "$1"',
 589+ 'survey-err-duplicate-name' => 'Xa existe unha enquisa chamada "$1"',
 590+ 'survey-err-ids-xor-names' => 'Cómpre dar ou ben os identificadores ou ben os nomes das enquisas para facer a pescuda',
 591+ 'survey-question-type-text' => 'Campo de texto de liña única',
 592+ 'survey-question-type-number' => 'Número',
 593+ 'survey-question-type-select' => 'Menú despregable',
 594+ 'survey-question-type-radio' => 'Botóns radiais',
 595+ 'survey-question-type-textarea' => 'Campo de texto con múltiples liñas',
 596+ 'survey-question-type-check' => 'Caixa de verificación',
 597+ 'survey-user-type-all' => 'Todos',
 598+ 'survey-user-type-loggedin' => 'Usuarios rexistrados',
 599+ 'survey-user-type-confirmed' => 'Usuarios confirmados',
 600+ 'survey-user-type-editor' => 'Editores',
 601+ 'survey-user-type-anon' => 'Usuarios anónimos',
 602+ 'survey-navigation-edit' => '[[Special:Survey/$1|Editar a enquisa]]',
 603+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|Completar esta enquisa]]',
 604+ 'survey-navigation-list' => '[[Special:Surveys|Lista de enquisas]]',
 605+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|Ollar as estatísticas]]',
 606+ 'surveys-special-addnew' => 'Engadir unha nova enquisa',
 607+ 'surveys-special-namedoc' => 'Escriba un identificador (ID) único para a nova enquisa. Máis adiante non se poderá cambiar. Por exemplo: motivación-dos-editores.',
 608+ 'surveys-special-newname' => 'ID da nova enquisa:',
 609+ 'surveys-special-add' => 'Engadir a enquisa',
 610+ 'surveys-special-existing' => 'Enquisas existentes',
 611+ 'surveys-special-title' => 'Título',
 612+ 'surveys-special-status' => 'Estado',
 613+ 'surveys-special-stats' => 'Estatísticas',
 614+ 'surveys-special-edit' => 'Editar',
 615+ 'surveys-special-save' => 'Gardar',
 616+ 'surveys-special-delete' => 'Borrar',
 617+ 'surveys-special-enabled' => 'Activa',
 618+ 'surveys-special-disabled' => 'Inactiva',
 619+ 'surveys-special-confirm-delete' => 'Está seguro de querer borrar esta enquisa?',
 620+ 'surveys-special-delete-failed' => 'Erro ao borrar a enquisa.',
 621+ 'survey-special-label-usertype' => 'Usuarios que deberían obter a enquisa',
 622+ 'survey-special-label-minpages' => 'Cantidade mínima de páxinas que o usuario ten que visitar antes de obter a enquisa',
 623+ 'surveys-takesurvey-loading' => 'Cargando a enquisa...',
 624+ 'surveys-takesurvey-nosuchsurvey' => 'A enquisa solicitada non existe.',
 625+ 'surveys-takesurvey-warn-notenabled' => 'Esta enquisa aínda non está activa, e polo tanto non é visible para os usuarios.',
 626+ 'surveys-takesurvey-surveynotenabled' => 'A enquisa solicitada aínda non está activa.',
 627+ 'surveys-surveystats-nosuchsurvey' => 'A enquisa solicitada non existe. Pode atopar unha lista das enquisas dispoñibles en [[Special:Surveys]]',
 628+ 'surveys-surveystats-name' => 'ID da enquisa',
 629+ 'surveys-surveystats-title' => 'Título da enquisa',
 630+ 'surveys-surveystats-status' => 'Estado da enquisa',
 631+ 'surveys-surveystats-questioncount' => 'Número de preguntas',
 632+ 'surveys-surveystats-submissioncount' => 'Número de envíos',
 633+ 'surveys-surveystats-enabled' => 'Activa',
 634+ 'surveys-surveystats-disabled' => 'Inactiva',
 635+ 'surveys-surveystats-questions' => 'Estatísticas da pregunta',
 636+ 'surveys-surveystats-question-type' => 'Tipo de pregunta',
 637+ 'surveys-surveystats-question-text' => 'Texto da pregunta',
 638+ 'surveys-surveystats-question-answercount' => 'Número de respostas',
 639+ 'surveys-surveystats-question-answers' => 'Respostas máis habituais',
 640+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|resposta|respostas}})',
 641+ 'surveys-surveystats-unchecked' => 'Desmarcada',
 642+ 'surveys-surveystats-checked' => 'Marcada',
 643+ 'surveys-special-unknown-name' => 'Non hai ningunha enquisa co ID solicitado.',
 644+ 'survey-special-label-name' => 'ID da enquisa',
 645+ 'survey-special-label-title' => 'Título da enquisa',
 646+ 'survey-special-label-enabled' => 'Enquisa activa',
 647+ 'survey-special-label-ratio' => 'Porcentaxe de persoas ás que mostrar a enquisa',
 648+ 'survey-special-label-add-first' => 'Engadir unha pregunta',
 649+ 'survey-special-label-add-another' => 'Engadir outra pregunta',
 650+ 'survey-special-label-addquestion' => 'Nova pregunta',
 651+ 'survey-question-label-nr' => 'Pregunta nº$1',
 652+ 'survey-special-label-required' => 'Cómpre a pregunta',
 653+ 'survey-special-label-type' => 'Tipo de pregunta',
 654+ 'survey-special-label-text' => 'Texto da pregunta',
 655+ 'survey-special-remove' => 'Eliminar a pregunta',
 656+ 'survey-special-remove-confirm' => 'Está seguro de querer borrar esta pregunta?',
 657+ 'survey-special-label-header' => 'Texto que mostrar enriba da enquisa',
 658+ 'survey-special-label-footer' => 'Texto que mostrar debaixo da enquisa',
 659+ 'survey-special-label-thanks' => 'Mensaxe de agradecemento que mostrar despois do envío da enquisa',
 660+ 'survey-special-label-answers' => 'Respostas dispoñibles, unha por liña.',
 661+ 'survey-jquery-submit' => 'Enviar',
 662+ 'survey-jquery-finish' => 'Rematar',
 663+ 'survey-jquery-load-failed' => 'Non se puido cargar a enquisa.',
 664+);
 665+
 666+/** Swiss German (Alemannisch)
 667+ * @author Als-Chlämens
 668+ */
 669+$messages['gsw'] = array(
 670+ 'surveys-special-addnew' => 'E neiji Umfroog starte',
 671+ 'surveys-special-add' => 'Umfroog dezuefiege',
 672+ 'surveys-special-existing' => "Umfrooge, wo's scho git",
 673+ 'surveys-special-title' => 'Titel',
 674+ 'surveys-special-status' => 'Status',
 675+ 'surveys-special-stats' => 'Statischtike',
 676+ 'surveys-special-edit' => 'Bearbeite',
 677+ 'surveys-special-save' => 'Spychere',
 678+ 'surveys-special-delete' => 'Lösche',
 679+ 'surveys-special-enabled' => 'Aktiviert',
 680+ 'surveys-special-disabled' => 'Deaktiviert',
 681+ 'surveys-special-confirm-delete' => 'Bisch sicher, ass Du die Umfroog witt lesche?',
 682+ 'surveys-special-delete-failed' => 'Die Umfroog het nit chönne glöscht werde.',
 683+ 'surveys-takesurvey-loading' => 'Die Umfroog wird glade...',
 684+);
 685+
 686+/** Upper Sorbian (Hornjoserbsce)
 687+ * @author Michawiki
 688+ */
 689+$messages['hsb'] = array(
 690+ 'surveys-special-title' => 'Titul',
 691+ 'surveys-special-status' => 'Status',
 692+ 'surveys-special-stats' => 'Statistika',
 693+ 'surveys-special-edit' => 'Wobdźěłać',
 694+ 'surveys-special-save' => 'Składować',
 695+ 'surveys-special-enabled' => 'Zmóžnjeny',
 696+ 'surveys-special-disabled' => 'Znjemóžnjeny',
 697+ 'surveys-surveystats-enabled' => 'Zmóžnjeny',
 698+ 'surveys-surveystats-disabled' => 'Znjemóžnjeny',
 699+ 'survey-question-label-nr' => 'Prašenje #$1',
 700+);
 701+
 702+/** Interlingua (Interlingua)
 703+ * @author McDutchie
 704+ */
 705+$messages['ia'] = array(
 706+ 'survey-desc' => 'Instrumento de questionario pro MediaWiki',
 707+ 'right-surveyadmin' => 'Gerer questionarios',
 708+ 'right-surveysubmit' => 'Participar in questionarios',
 709+ 'group-surveyadmin' => 'Administratores de questionario',
 710+ 'group-surveyadmin-member' => '{{GENDER:$1|administrator|administratrice}} de questionario',
 711+ 'grouppage-surveyadmin' => 'Project:Administratores de questionario',
 712+ 'group-surveysubmit' => 'Participantes de questionario',
 713+ 'group-surveysubmit-member' => '{{GENDER:$1|participante}} de questionario',
 714+ 'grouppage-surveysubmit' => 'Project:Participantes de questionario',
 715+ 'special-editsurvey' => 'Administra questionario',
 716+ 'special-surveys' => 'Administration de questionarios',
 717+ 'special-surveystats' => 'Statisticas de questionario',
 718+ 'special-takesurvey' => 'Responder a questionario',
 719+ 'survey-err-id-xor-name' => 'Es necessari fornir le ID o le nomine del questionario a submitter',
 720+ 'survey-err-survey-name-unknown' => 'Non existe un questionario con le nomine "$1"',
 721+ 'survey-err-duplicate-name' => 'Jam existe un questionario con le nomine "$1"',
 722+ 'survey-err-ids-xor-names' => 'Es necessari fornir le IDs o le nomines del questionarios a consultar',
 723+ 'survey-question-type-text' => 'Campo de texto con un linea',
 724+ 'survey-question-type-number' => 'Numero',
 725+ 'survey-question-type-select' => 'Menu disrolante',
 726+ 'survey-question-type-radio' => 'Buttones de radio',
 727+ 'survey-question-type-textarea' => 'Campo de texto con plure lineas',
 728+ 'survey-question-type-check' => 'Quadrato de selection',
 729+ 'survey-user-type-all' => 'Omnes',
 730+ 'survey-user-type-loggedin' => 'Usatores authenticate',
 731+ 'survey-user-type-confirmed' => 'Usatores confirmate',
 732+ 'survey-user-type-editor' => 'Redactores',
 733+ 'survey-user-type-anon' => 'Usatores anonyme',
 734+ 'survey-navigation-edit' => '[[Special:Survey/$1|Modificar iste questionario]]',
 735+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|Responder a iste questionario]]',
 736+ 'survey-navigation-list' => '[[Special:Surveys|Lista de questionarios]]',
 737+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|Vider statisticas]]',
 738+ 'surveys-special-addnew' => 'Adder un nove questionario',
 739+ 'surveys-special-namedoc' => 'Entra un identificator unic (ID) pro le nove questionario. Non pote esser cambiate plus tarde. Per exemplo: motivation-redactores.',
 740+ 'surveys-special-newname' => 'ID del nove questionario:',
 741+ 'surveys-special-add' => 'Adder questionario',
 742+ 'surveys-special-existing' => 'Questionarios existente',
 743+ 'surveys-special-title' => 'Titulo',
 744+ 'surveys-special-status' => 'Stato',
 745+ 'surveys-special-stats' => 'Statisticas',
 746+ 'surveys-special-edit' => 'Modificar',
 747+ 'surveys-special-save' => 'Salveguardar',
 748+ 'surveys-special-delete' => 'Deler',
 749+ 'surveys-special-enabled' => 'Activate',
 750+ 'surveys-special-disabled' => 'Disactivate',
 751+ 'surveys-special-confirm-delete' => 'Es tu secur de voler deler iste questionario?',
 752+ 'surveys-special-delete-failed' => 'Deletion de questionario fallite.',
 753+ 'survey-special-label-usertype' => 'Usatores qui debe reciper le questionario',
 754+ 'survey-special-label-minpages' => 'Numero minime de paginas que le usator debe visitar ante de reciper le questionario',
 755+ 'surveys-takesurvey-loading' => 'Carga questionario...',
 756+ 'surveys-takesurvey-nosuchsurvey' => 'Le questionario requestate non existe.',
 757+ 'surveys-takesurvey-warn-notenabled' => 'Iste questionario non ha ancora essite activate, e dunque non es visibile pro le usatores.',
 758+ 'surveys-takesurvey-surveynotenabled' => 'Le questionario requestate non ha ancora essite activate.',
 759+ 'surveys-surveystats-nosuchsurvey' => 'Le questionario requestate non existe. Tu pote vider un [[Special:Surveys|lista de questionarios disponibile]].',
 760+ 'surveys-surveystats-name' => 'ID del questionario',
 761+ 'surveys-surveystats-title' => 'Titulo del questionario',
 762+ 'surveys-surveystats-status' => 'Stato del questionario',
 763+ 'surveys-surveystats-questioncount' => 'Numero de questiones',
 764+ 'surveys-surveystats-submissioncount' => 'Numero de submissiones',
 765+ 'surveys-surveystats-enabled' => 'Active',
 766+ 'surveys-surveystats-disabled' => 'Inactive',
 767+ 'surveys-surveystats-questions' => 'Statisticas de question',
 768+ 'surveys-surveystats-question-type' => 'Typo de question',
 769+ 'surveys-surveystats-question-text' => 'Texto de question',
 770+ 'surveys-surveystats-question-answercount' => 'Numero de responsas',
 771+ 'surveys-surveystats-question-answers' => 'Responsas le plus frequente',
 772+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|responsa|responsas}})',
 773+ 'surveys-surveystats-unchecked' => 'Non marcate',
 774+ 'surveys-surveystats-checked' => 'Marcate',
 775+ 'surveys-special-unknown-name' => 'Non existe un questionario con le ID requestate.',
 776+ 'survey-special-label-name' => 'ID del questionario',
 777+ 'survey-special-label-title' => 'Titulo del questionario',
 778+ 'survey-special-label-enabled' => 'Questionario activate',
 779+ 'survey-special-label-ratio' => 'Percentage de personas a qui monstrar le questionario',
 780+ 'survey-special-label-add-first' => 'Adder question',
 781+ 'survey-special-label-add-another' => 'Adder un altere question',
 782+ 'survey-special-label-addquestion' => 'Nove question',
 783+ 'survey-question-label-nr' => 'Question №$1',
 784+ 'survey-special-label-required' => 'Question es obligatori',
 785+ 'survey-special-label-type' => 'Typo de question',
 786+ 'survey-special-label-text' => 'Texto de question',
 787+ 'survey-special-remove' => 'Remover question',
 788+ 'survey-special-remove-confirm' => 'Es tu secur de voler remover iste question?',
 789+ 'survey-special-label-header' => 'Texto a monstrar supra le questionario',
 790+ 'survey-special-label-footer' => 'Texto a monstrar infra le questionario',
 791+ 'survey-special-label-thanks' => 'Message de regratiamento a monstrar post submission del questionario',
 792+ 'survey-special-label-answers' => 'Responsas disponibile, un per linea.',
 793+ 'survey-jquery-submit' => 'Submitter',
 794+ 'survey-jquery-finish' => 'Finir',
 795+ 'survey-jquery-load-failed' => 'Non poteva cargar le questionario.',
 796+);
 797+
 798+/** Luxembourgish (Lëtzebuergesch)
 799+ * @author Robby
 800+ */
 801+$messages['lb'] = array(
 802+ 'survey-desc' => 'Tool fir Ëmfroe fir MediaWiki',
 803+ 'right-surveyadmin' => 'Ëmfroe geréieren',
 804+ 'right-surveysubmit' => 'Bäi Ëmfroe matmaachen',
 805+ 'special-editsurvey' => 'Gestioun vun Ëmfroen',
 806+ 'special-surveys' => 'Gestioun vun Ëmfroen',
 807+ 'special-surveystats' => 'Statistike vun Ëmfroen',
 808+ 'special-takesurvey' => 'Bäi der Ëmfro matmaachen',
 809+ 'survey-err-survey-name-unknown' => 'Et gëtt keng Ëmfro mam Numm "$1"',
 810+ 'survey-err-duplicate-name' => 'Et gëtt schonn eng Ëmfro mam Numm "$1"',
 811+ 'survey-question-type-number' => 'Zuel',
 812+ 'survey-user-type-all' => 'Jiddwereen',
 813+ 'survey-user-type-loggedin' => 'Ageloggte Benotzer',
 814+ 'survey-user-type-confirmed' => 'Confirméiert Benotzer',
 815+ 'survey-user-type-anon' => 'Anonym Benotzer',
 816+ 'survey-navigation-edit' => '[[Special:Survey/$1|Ännert dës Ëmfro]]',
 817+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|Bedeelegt Iech un dëser Ëmfro]]',
 818+ 'survey-navigation-list' => '[[Special:Surveys|Lëscht vun den Ëmfroen]]',
 819+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|Statistike vun den Ëmfroe weisen]]',
 820+ 'surveys-special-addnew' => 'Eng nei Ëmfro derbäisetzen',
 821+ 'surveys-special-newname' => "Nei ID fir d'Ëmfro:",
 822+ 'surveys-special-add' => 'Ëmfro derbäisetzen',
 823+ 'surveys-special-existing' => 'Ëmfroen déi et gëtt',
 824+ 'surveys-special-title' => 'Titel',
 825+ 'surveys-special-status' => 'Status',
 826+ 'surveys-special-stats' => 'Statistiken',
 827+ 'surveys-special-edit' => 'Änneren',
 828+ 'surveys-special-save' => 'Späicheren',
 829+ 'surveys-special-delete' => 'Läschen',
 830+ 'surveys-special-enabled' => 'Aktivéiert',
 831+ 'surveys-special-disabled' => 'Desaktivéiert',
 832+ 'surveys-special-confirm-delete' => 'Sidd Dir sécher datt Dir dës Ëmfro läsche wëllt?',
 833+ 'surveys-special-delete-failed' => "D'Ëmfro konnt net geläscht ginn.",
 834+ 'survey-special-label-usertype' => "Benotzer deenen d'Ëmfro gewise soll ginn",
 835+ 'survey-special-label-minpages' => "D'Mindestzuel vu Säiten, déi e Benotzer muss gekuckt hu ier hie bäi der Ëmfro matmaache kann",
 836+ 'surveys-takesurvey-loading' => "D'Ëmfro gëtt gelueden...",
 837+ 'surveys-takesurvey-nosuchsurvey' => 'Déi gefroten Ëmfro gëtt et net.',
 838+ 'surveys-takesurvey-warn-notenabled' => 'Dës Ëmfro ass nach net aktivéiert a kann dowéinst vun de Benotzer nach net gesi ginn.',
 839+ 'surveys-surveystats-name' => 'ID vun der Ëmfro',
 840+ 'surveys-surveystats-title' => 'Titel vun der Ëmfro',
 841+ 'surveys-surveystats-questioncount' => 'Zuel vun de Froen',
 842+ 'surveys-surveystats-enabled' => 'Aktivéiert',
 843+ 'surveys-surveystats-disabled' => 'Desaktivéiert',
 844+ 'surveys-surveystats-questions' => 'Statistike vun de Froen',
 845+ 'surveys-surveystats-question-type' => 'Typ vun der Fro',
 846+ 'surveys-surveystats-question-text' => 'Text vun der Fro',
 847+ 'surveys-surveystats-question-answercount' => 'Zuel vun den Äntwerten',
 848+ 'surveys-surveystats-question-answers' => 'Déi am dackste genannten Äntwerten',
 849+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|Äntwert|Äntwerten}})',
 850+ 'surveys-surveystats-unchecked' => 'Netnogekuckt',
 851+ 'surveys-surveystats-checked' => 'Nogekuckt',
 852+ 'surveys-special-unknown-name' => 'Et gëtt keng Ëmfro mat der ugefroter ID.',
 853+ 'survey-special-label-name' => 'ID vun der Ëmfro',
 854+ 'survey-special-label-title' => 'Titel vun der Ëmfro',
 855+ 'survey-special-label-enabled' => 'Ëmfro aktivéiert',
 856+ 'survey-special-label-ratio' => "Prozentsaz vun de Benotzer déi d'Ëmfro gewise kréien",
 857+ 'survey-special-label-add-first' => 'Fro derbäisetzen',
 858+ 'survey-special-label-add-another' => 'Eng aner Fro derbäisetzen',
 859+ 'survey-special-label-addquestion' => 'Nei Fro',
 860+ 'survey-question-label-nr' => 'Fro #$1',
 861+ 'survey-special-label-required' => "D'Äntwert op dës Fro ass obligatoresch",
 862+ 'survey-special-label-type' => 'Typ vun der Fro',
 863+ 'survey-special-label-text' => 'Text vun der Fro',
 864+ 'survey-special-remove' => 'Fro ewechhuelen',
 865+ 'survey-special-remove-confirm' => 'Sidd Dir sécher datt Dir dës Fro ewechhuele wëllt?',
 866+ 'survey-special-label-header' => 'Text deen iwwer der Ëmfro gewise gëtt',
 867+ 'survey-special-label-footer' => 'Text deen ënnert der Ëmfro gewise gëtt',
 868+ 'survey-special-label-answers' => 'Disponibel Äntwerten, eng pro Linn.',
 869+ 'survey-jquery-finish' => 'Fäerdeg maachen',
 870+ 'survey-jquery-load-failed' => "D'Ëmfro konnt net geluede ginn.",
 871+);
 872+
 873+/** Lithuanian (Lietuvių)
 874+ * @author Eitvys200
 875+ */
 876+$messages['lt'] = array(
 877+ 'survey-desc' => 'Apklausos įrankis puslapiui MediaWiki',
 878+ 'right-surveyadmin' => 'Valdyti apklausas',
 879+ 'special-editsurvey' => 'Apklausos administratorius',
 880+ 'special-surveys' => 'Apklausų administratorius',
 881+ 'special-surveystats' => 'Apklausos statistika',
 882+ 'special-takesurvey' => 'Atlikti apklausą',
 883+ 'survey-err-survey-name-unknown' => 'Nėra jokios apklausos pavadinimu "$1"',
 884+ 'survey-err-duplicate-name' => 'Jau yra apklausa pavadinimu "$1"',
 885+ 'survey-question-type-number' => 'Skaičius',
 886+ 'survey-question-type-select' => 'Išskleidžiamas meniu',
 887+ 'survey-user-type-all' => 'Visi',
 888+ 'survey-user-type-loggedin' => 'Prisijungę naudotojai',
 889+ 'survey-user-type-confirmed' => 'Patvirtinti naudotojai',
 890+ 'survey-user-type-editor' => 'Redaktoriai',
 891+ 'survey-user-type-anon' => 'Anoniminiai naudotojai',
 892+ 'surveys-special-addnew' => 'Pridėti naują apklausą',
 893+ 'surveys-special-newname' => 'Naujos apklausos ID:',
 894+ 'surveys-special-add' => 'Pridėti apklausą',
 895+ 'surveys-special-existing' => 'Egzistuojančios apklausos',
 896+ 'surveys-special-title' => 'Pavadinimas',
 897+ 'surveys-special-status' => 'Būsena',
 898+ 'surveys-special-edit' => 'Redaguoti',
 899+ 'surveys-special-save' => 'Išsaugoti',
 900+ 'surveys-special-delete' => 'Ištrinti',
 901+ 'surveys-special-confirm-delete' => 'Ar tikrai norite ištrinti šią apklausą?',
 902+ 'surveys-special-delete-failed' => 'Nepavyko ištrinti apklausą.',
 903+ 'surveys-takesurvey-loading' => 'Kraunama apklausa...',
 904+ 'surveys-surveystats-name' => 'Apklausos ID',
 905+ 'surveys-surveystats-title' => 'Apklausos pavadinimas',
 906+);
 907+
 908+/** Macedonian (Македонски)
 909+ * @author Bjankuloski06
 910+ */
 911+$messages['mk'] = array(
 912+ 'survey-desc' => 'Алатка на МедијаВики за анкети',
 913+ 'right-surveyadmin' => 'Раководење со анкети',
 914+ 'right-surveysubmit' => 'Учествувајте во анкети',
 915+ 'group-surveyadmin' => 'Анкетни администратори',
 916+ 'group-surveyadmin-member' => '{{GENDER:$1|анкетен администратор}}',
 917+ 'grouppage-surveyadmin' => 'Project:Анкетирани',
 918+ 'group-surveysubmit' => 'Анкетирани',
 919+ 'group-surveysubmit-member' => '{{GENDER:$1|анкетиран}}',
 920+ 'grouppage-surveysubmit' => 'Project:Анкетирани',
 921+ 'special-editsurvey' => 'Администратор на анкетата',
 922+ 'special-surveys' => 'Анкетен администратор',
 923+ 'special-surveystats' => 'Статистики на анкетата',
 924+ 'special-takesurvey' => 'Пополнете ја анкетата',
 925+ 'survey-err-id-xor-name' => 'Треба да ја наведете назнаката или името на анкетата што сакате да ја поднесете',
 926+ 'survey-err-survey-name-unknown' => 'Нема постои анкета со наслов „$1“',
 927+ 'survey-err-duplicate-name' => 'Веќе постои анкета со наслов „$1“',
 928+ 'survey-err-ids-xor-names' => 'Треба да ги наведете назнаките или имињата на анкетите што ги побарате',
 929+ 'survey-question-type-text' => 'Едноредно поле за текст',
 930+ 'survey-question-type-number' => 'Број',
 931+ 'survey-question-type-select' => 'Паѓачко мени',
 932+ 'survey-question-type-radio' => 'Радиокопчиња',
 933+ 'survey-question-type-textarea' => 'Повеќередно поле за текст',
 934+ 'survey-question-type-check' => 'Штикларник',
 935+ 'survey-user-type-all' => 'Секому',
 936+ 'survey-user-type-loggedin' => 'Најавени корисници',
 937+ 'survey-user-type-confirmed' => 'Потврдени корисници',
 938+ 'survey-user-type-editor' => 'Уредници',
 939+ 'survey-user-type-anon' => 'Анонимни корисници',
 940+ 'survey-navigation-edit' => '[[Special:Survey/$1|Уредете ја анкетава]]',
 941+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|Пополнете ја анкетава]]',
 942+ 'survey-navigation-list' => '[[Special:Surveys|Список на анкети]]',
 943+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|Статистики]]',
 944+ 'surveys-special-addnew' => 'Додај нова анкета',
 945+ 'surveys-special-namedoc' => 'Задајте единствена назнака (ID) за новата анкета. Ова не може да се менува подоцна. На пример: мотивација-на-уредниците.',
 946+ 'surveys-special-newname' => 'Назнака на новата анкета:',
 947+ 'surveys-special-add' => 'Додај анкета',
 948+ 'surveys-special-existing' => 'Постоечки анкети',
 949+ 'surveys-special-title' => 'Наслов',
 950+ 'surveys-special-status' => 'Статус',
 951+ 'surveys-special-stats' => 'Статистики',
 952+ 'surveys-special-edit' => 'Уреди',
 953+ 'surveys-special-save' => 'Зачувај',
 954+ 'surveys-special-delete' => 'Избриши',
 955+ 'surveys-special-enabled' => 'Овозможено',
 956+ 'surveys-special-disabled' => 'Оневозможено',
 957+ 'surveys-special-confirm-delete' => 'Дали сте сигурни дека сакате да ја избришете оваа анкета?',
 958+ 'surveys-special-delete-failed' => 'Не успеав да ја избришам анкетата.',
 959+ 'survey-special-label-usertype' => 'Корисниците што треба да ја добијат анкетата',
 960+ 'survey-special-label-minpages' => 'Колку најмалку страници треба да посети корисникот за да ја добие анкетата',
 961+ 'surveys-takesurvey-loading' => 'Ја вчитувам анкетата...',
 962+ 'surveys-takesurvey-nosuchsurvey' => 'Бараната анкета не постои.',
 963+ 'surveys-takesurvey-warn-notenabled' => 'Оваа анкета сè уште не е достапна, па затоа не е ни видлива за корисниците.',
 964+ 'surveys-takesurvey-surveynotenabled' => 'Бараната анкета сè уште не е овозможена.',
 965+ 'surveys-surveystats-nosuchsurvey' => 'Бараната анкета не постои. Список на расположиви анкети ќе најдете на [[Special:Surveys]]',
 966+ 'surveys-surveystats-name' => 'Назнака (ID) на анкетата',
 967+ 'surveys-surveystats-title' => 'Наслов на анкетата',
 968+ 'surveys-surveystats-status' => 'Статус на анкетата',
 969+ 'surveys-surveystats-questioncount' => 'Број на прашања',
 970+ 'surveys-surveystats-submissioncount' => 'Број на поснесувања',
 971+ 'surveys-surveystats-enabled' => 'Овозможено',
 972+ 'surveys-surveystats-disabled' => 'Оневозможено',
 973+ 'surveys-surveystats-questions' => 'Статистики за прашањата',
 974+ 'surveys-surveystats-question-type' => 'Тип на прашање',
 975+ 'surveys-surveystats-question-text' => 'Текст на прашањето',
 976+ 'surveys-surveystats-question-answercount' => 'Број на одговори',
 977+ 'surveys-surveystats-question-answers' => 'Најзастапени одговори',
 978+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|одговор|одговори}})',
 979+ 'surveys-surveystats-unchecked' => 'Непроверено',
 980+ 'surveys-surveystats-checked' => 'Проверено',
 981+ 'surveys-special-unknown-name' => 'Не постои анкета со бараната назнака',
 982+ 'survey-special-label-name' => 'Назнака на анкетата',
 983+ 'survey-special-label-title' => 'Наслов на анкетата',
 984+ 'survey-special-label-enabled' => 'Анкетата е овозможена',
 985+ 'survey-special-label-ratio' => 'На колкав постоток од посетителите да им се прикаже анкетата',
 986+ 'survey-special-label-add-first' => 'Додај прашање',
 987+ 'survey-special-label-add-another' => 'Додај друго прашање',
 988+ 'survey-special-label-addquestion' => 'Ново прашање',
 989+ 'survey-question-label-nr' => 'Прашање бр. $1',
 990+ 'survey-special-label-required' => 'Прашањето е задолжително',
 991+ 'survey-special-label-type' => 'Тип на прашање',
 992+ 'survey-special-label-text' => 'Текст на прашањето',
 993+ 'survey-special-remove' => 'Отстрани прашање',
 994+ 'survey-special-remove-confirm' => 'Дали сте сигурни дека сакате да го отстраните ова прашање?',
 995+ 'survey-special-label-header' => 'Текстот што ќе стои над анкетата',
 996+ 'survey-special-label-footer' => 'Текстот што ќе стои под анкетата',
 997+ 'survey-special-label-thanks' => 'Порака за заблагодарување што се појавува по поднесувањето на анкетата',
 998+ 'survey-special-label-answers' => 'Расположиви одговори, по еден во секој ред.',
 999+ 'survey-jquery-submit' => 'Поднеси',
 1000+ 'survey-jquery-finish' => 'Готово',
 1001+ 'survey-jquery-load-failed' => 'Не можев да ја вчитам анкетата.',
 1002+);
 1003+
 1004+/** Dutch (Nederlands)
 1005+ * @author SPQRobin
 1006+ * @author Siebrand
 1007+ */
 1008+$messages['nl'] = array(
 1009+ 'survey-desc' => 'Vragenlijstenhulpmiddel voor MediaWiki',
 1010+ 'right-surveyadmin' => 'Vragenlijsten beheren',
 1011+ 'right-surveysubmit' => 'Vragenlijsten beantwoorden',
 1012+ 'group-surveyadmin' => 'Vragenlijstbeheerders',
 1013+ 'group-surveyadmin-member' => '{{GENDER:$1|vragenlijstbeheerder}}',
 1014+ 'grouppage-surveyadmin' => 'Project:Vragenlijstbeheerders',
 1015+ 'group-surveysubmit' => 'Vragenlijstdeelnemers',
 1016+ 'group-surveysubmit-member' => '{{GENDER:$1|vragenlijstdeelnemer|vragenlijstdeelneemster}}',
 1017+ 'grouppage-surveysubmit' => 'Project:Vragenlijstdeelnemers',
 1018+ 'special-editsurvey' => 'Vragenlijstbeheer',
 1019+ 'special-surveys' => 'Vragenlijstenbeheer',
 1020+ 'special-surveystats' => 'Vragenlijststatistieken',
 1021+ 'special-takesurvey' => 'Vragenlijst beantwoorden',
 1022+ 'survey-err-id-xor-name' => 'U moet ofwel de ID of de naam opgeven om de vragenlijst op te slaan.',
 1023+ 'survey-err-survey-name-unknown' => 'Er is geen vragenlijst met de naam "$1"',
 1024+ 'survey-err-duplicate-name' => 'Er is al een vragenlijst met de naam "$1"',
 1025+ 'survey-err-ids-xor-names' => "U moet ofwel de ID's of de namen opgeven van de vragenlijsten die u wilt vinden",
 1026+ 'survey-question-type-text' => 'Tekstveld met één regel',
 1027+ 'survey-question-type-number' => 'Getal',
 1028+ 'survey-question-type-select' => 'Dropdownmenu',
 1029+ 'survey-question-type-radio' => 'Keuzerondjes',
 1030+ 'survey-question-type-textarea' => 'Tekstveld met meerdere regels',
 1031+ 'survey-question-type-check' => 'Vinkvakje',
 1032+ 'survey-user-type-all' => 'Iedereen',
 1033+ 'survey-user-type-loggedin' => 'Aangemelde gebruikers',
 1034+ 'survey-user-type-confirmed' => 'Bevestigde gebruikers',
 1035+ 'survey-user-type-editor' => 'Redacteuren',
 1036+ 'survey-user-type-anon' => 'Anonieme gebruikers',
 1037+ 'survey-navigation-edit' => '[[Special:Survey/$1|Deze vragenlijst bewerken]]',
 1038+ 'survey-navigation-take' => '[[Special:TakeSurvey/$1|Deelnemen aan deze vragenlijst]]',
 1039+ 'survey-navigation-list' => '[[Special:Surveys|Lijst met vragenlijsten]]',
 1040+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|Statistieken bekijken]]',
 1041+ 'surveys-special-addnew' => 'Een nieuwe vragenlijst toevoegen',
 1042+ 'surveys-special-namedoc' => 'Geef een unieke naam (ID) op voor de nieuwe vragenlijst. Deze kan later niet worden gewijzigd. Bijvoorbeeld: redacteurenmotivatie.',
 1043+ 'surveys-special-newname' => 'Nieuw vragenlijst-ID:',
 1044+ 'surveys-special-add' => 'Vragenlijst toevoegen',
 1045+ 'surveys-special-existing' => 'Bestaande vragenlijsten',
 1046+ 'surveys-special-title' => 'Naam',
 1047+ 'surveys-special-status' => 'Status',
 1048+ 'surveys-special-stats' => 'Statistieken',
 1049+ 'surveys-special-edit' => 'Bewerken',
 1050+ 'surveys-special-save' => 'Opslaan',
 1051+ 'surveys-special-delete' => 'Verwijderen',
 1052+ 'surveys-special-enabled' => 'Ingeschakeld',
 1053+ 'surveys-special-disabled' => 'Uitgeschakeld',
 1054+ 'surveys-special-confirm-delete' => 'Weet u zeker dat u deze vragenlijst wilt verwijderen?',
 1055+ 'surveys-special-delete-failed' => 'Het verwijderen van de vragenlijst is mislukt.',
 1056+ 'survey-special-label-usertype' => 'Gebruikers die de vragenlijst mogen invullen',
 1057+ 'survey-special-label-minpages' => "Minimum aantal pagina's dat de gebruiker moet bezoeken voordat die de vragenlijst te zien krijgt",
 1058+ 'surveys-takesurvey-loading' => 'De vragenlijst wordt geladen...',
 1059+ 'surveys-takesurvey-nosuchsurvey' => 'De opgevraagde vragenlijst bestaat niet.',
 1060+ 'surveys-takesurvey-warn-notenabled' => 'Deze vragenlijst is nog niet ingeschakeld en is daarom niet zichtbaar voor gebruikers.',
 1061+ 'surveys-takesurvey-surveynotenabled' => 'De opgevraagde vragenlijst is niet nog ingeschakeld.',
 1062+ 'surveys-surveystats-nosuchsurvey' => 'De opgevraagde vragenlijst bestaat niet. U kunt een [[Special:Surveys|lijst met beschikbare vragenlijsten]] bekijken.',
 1063+ 'surveys-surveystats-name' => 'Vragenlijst-ID',
 1064+ 'surveys-surveystats-title' => 'Naam van de vragenlijst',
 1065+ 'surveys-surveystats-status' => 'Vragenlijststatus',
 1066+ 'surveys-surveystats-questioncount' => 'Aantal vragen',
 1067+ 'surveys-surveystats-submissioncount' => 'Aantal inzendingen',
 1068+ 'surveys-surveystats-enabled' => 'Ingeschakeld',
 1069+ 'surveys-surveystats-disabled' => 'Uitgeschakeld',
 1070+ 'surveys-surveystats-questions' => 'Vraagstatistieken',
 1071+ 'surveys-surveystats-question-type' => 'Type vraag',
 1072+ 'surveys-surveystats-question-text' => 'Vraagtekst',
 1073+ 'surveys-surveystats-question-answercount' => 'Aantal antwoorden',
 1074+ 'surveys-surveystats-question-answers' => 'Meest gegeven antwoorden',
 1075+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|antwoord|antwoorden}})',
 1076+ 'surveys-surveystats-unchecked' => 'Uitgevinkt',
 1077+ 'surveys-surveystats-checked' => 'Aangevinkt',
 1078+ 'surveys-special-unknown-name' => 'Er is geen vragenlijst met het opgevraagde ID.',
 1079+ 'survey-special-label-name' => 'Vragenlijst-ID',
 1080+ 'survey-special-label-title' => 'Naam van de vragenlijst',
 1081+ 'survey-special-label-enabled' => 'Vragenlijst ingeschakeld',
 1082+ 'survey-special-label-ratio' => 'Percentage gebruikers om deze vragenlijst aan te laten zien',
 1083+ 'survey-special-label-add-first' => 'Vraag toevoegen',
 1084+ 'survey-special-label-add-another' => 'Nog een vraag toevoegen',
 1085+ 'survey-special-label-addquestion' => 'Nieuwe vraag',
 1086+ 'survey-question-label-nr' => 'Vraag #$1',
 1087+ 'survey-special-label-required' => 'Vraag is verplicht',
 1088+ 'survey-special-label-type' => 'Type vraag',
 1089+ 'survey-special-label-text' => 'Vraagtekst',
 1090+ 'survey-special-remove' => 'Vraag verwijderen',
 1091+ 'survey-special-remove-confirm' => 'Weet u zeker dat u deze vraag wilt verwijderen?',
 1092+ 'survey-special-label-header' => 'Tekst om boven de vragenlijst weer te geven',
 1093+ 'survey-special-label-footer' => 'Tekst om onder de vragenlijst weer te geven',
 1094+ 'survey-special-label-thanks' => 'Dankbericht om weer te geven na het inzenden van de vragenlijst',
 1095+ 'survey-special-label-answers' => 'Beschikbare antwoorden, één per regel.',
 1096+ 'survey-jquery-submit' => 'Opslaan',
 1097+ 'survey-jquery-finish' => 'Voltooien',
 1098+ 'survey-jquery-load-failed' => 'De vragenlijst kon niet worden geladen.',
 1099+);
 1100+
 1101+/** Polish (Polski)
 1102+ * @author Woytecr
 1103+ */
 1104+$messages['pl'] = array(
 1105+ 'survey-user-type-loggedin' => 'Zalogowani użytkownicy',
 1106+ 'survey-user-type-confirmed' => 'Zatwierdzeni użytkownicy',
 1107+ 'survey-user-type-editor' => 'Redaktorzy',
 1108+ 'survey-user-type-anon' => 'Anonimowi użytkownicy',
 1109+ 'surveys-special-title' => 'Tytuł',
 1110+ 'surveys-special-status' => 'Status',
 1111+ 'surveys-special-stats' => 'Statystyki',
 1112+ 'surveys-special-edit' => 'Edytuj',
 1113+ 'surveys-special-save' => 'Zapisz',
 1114+ 'surveys-special-delete' => 'Usuń',
 1115+);
 1116+
 1117+/** Pashto (پښتو)
 1118+ * @author Ahmed-Najib-Biabani-Ibrahimkhel
 1119+ */
 1120+$messages['ps'] = array(
 1121+ 'survey-user-type-editor' => 'سمونګران',
 1122+ 'surveys-special-status' => 'دريځ',
 1123+ 'surveys-special-edit' => 'سمول',
 1124+ 'surveys-special-save' => 'خوندي کول',
 1125+ 'surveys-special-delete' => 'ړنګول',
 1126+ 'survey-jquery-submit' => 'سپارل',
 1127+);
 1128+
 1129+/** Telugu (తెలుగు)
 1130+ * @author Veeven
 1131+ */
 1132+$messages['te'] = array(
 1133+ 'survey-question-type-number' => 'సంఖ్య',
 1134+ 'survey-user-type-all' => 'అందరూ',
 1135+ 'survey-user-type-anon' => 'అజ్ఞాత వాడుకరులు',
 1136+ 'survey-navigation-stats' => '[[Special:SurveyStats/$1|గణాంకాలను చూడండి]]',
 1137+ 'surveys-special-title' => 'శీర్షిక',
 1138+ 'surveys-special-status' => 'స్థితి',
 1139+ 'surveys-special-stats' => 'గణాంకాలు',
 1140+ 'surveys-special-save' => 'భద్రపరచు',
 1141+ 'surveys-special-delete' => 'తొలగించు',
 1142+ 'surveys-surveystats-questioncount' => 'ప్రశ్నల సంఖ్య',
 1143+ 'surveys-surveystats-questions' => 'ప్రశ్నల గణాంకాలు',
 1144+ 'surveys-surveystats-question-type' => 'ప్రశ్న రకం',
 1145+ 'surveys-surveystats-question-text' => 'ప్రశ్న పాఠ్యం',
 1146+ 'surveys-surveystats-question-answercount' => 'జవాబుల సంఖ్య',
 1147+ 'surveys-surveystats-question-answer' => '$1 ($2 {{PLURAL:$2|జవాబు|జవాబులు}})',
 1148+ 'survey-special-label-addquestion' => 'కొత్త ప్రశ్న',
 1149+ 'survey-special-label-required' => 'ప్రశ్న తప్పనిసరి',
 1150+ 'survey-special-label-type' => 'ప్రశ్న రకం',
 1151+ 'survey-special-label-text' => 'ప్రశ్న పాఠ్యం',
 1152+ 'survey-special-remove' => 'ప్రశ్నను తొలగించు',
 1153+);
 1154+
Property changes on: tags/extensions/Survey/REL_0_1_2/Survey.i18n.php
___________________________________________________________________
Added: svn:eol-style
11155 + native
Index: tags/extensions/Survey/REL_0_1_2/specials/SpecialSurveyPage.php
@@ -0,0 +1,135 @@
 2+<?php
 3+
 4+/**
 5+ * Base special page for special pages in the Survey extension,
 6+ * taking care of some common stuff and providing compatibility helpers.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SpecialSurveyPage.php
 11+ * @ingroup Survey
 12+ *
 13+ * @licence GNU GPL v3 or later
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+abstract class SpecialSurveyPage extends SpecialPage {
 17+
 18+ /**
 19+ * @see SpecialPage::getDescription
 20+ *
 21+ * @since 0.1
 22+ */
 23+ public function getDescription() {
 24+ return wfMsg( 'special-' . strtolower( $this->getName() ) );
 25+ }
 26+
 27+ /**
 28+ * Sets headers - this should be called from the execute() method of all derived classes!
 29+ *
 30+ * @since 0.1
 31+ */
 32+ public function setHeaders() {
 33+ $out = $this->getOutput();
 34+ $out->setArticleRelated( false );
 35+ $out->setRobotPolicy( 'noindex,nofollow' );
 36+ $out->setPageTitle( $this->getDescription() );
 37+ }
 38+
 39+ /**
 40+ * Main method.
 41+ *
 42+ * @since 0.1
 43+ *
 44+ * @param string $arg
 45+ */
 46+ public function execute( $subPage ) {
 47+ global $wgUser;
 48+
 49+ $this->setHeaders();
 50+ $this->outputHeader();
 51+
 52+ // If the user is authorized, display the page, if not, show an error.
 53+ if ( !$this->userCanExecute( $wgUser ) ) {
 54+ $this->displayRestrictionError();
 55+ return false;
 56+ }
 57+
 58+ return true;
 59+ }
 60+
 61+ /**
 62+ * Get the OutputPage being used for this instance.
 63+ * This overrides the getOutput method of Specialpage added in MediaWiki 1.18,
 64+ * and returns $wgOut for older versions.
 65+ *
 66+ * @since 0.1
 67+ *
 68+ * @return OutputPage
 69+ */
 70+ public function getOutput() {
 71+ return version_compare( $GLOBALS['wgVersion'], '1.18', '>=' ) ? parent::getOutput() : $GLOBALS['wgOut'];
 72+ }
 73+
 74+ /**
 75+ * Shortcut to get user's language.
 76+ * This overrides the getLang method of Specialpage added in MediaWiki 1.18,
 77+ * and returns $wgLang for older versions.
 78+ *
 79+ * @since 0.1
 80+ *
 81+ * @return Language
 82+ */
 83+ public function getLang() {
 84+ return version_compare( $GLOBALS['wgVersion'], '1.18', '>=' ) ? parent::getLang() : $GLOBALS['wgLang'];
 85+ }
 86+
 87+ /**
 88+ * Add resource loader modules or use fallback code for
 89+ * earlier versions of MediaWiki.
 90+ *
 91+ * @since 0.1
 92+ *
 93+ * @param string|array $modules
 94+ */
 95+ public function addModules( $modules ) {
 96+ $this->getOutput()->addModules( $modules );
 97+ }
 98+
 99+ /**
 100+ * Show a message in an error box.
 101+ *
 102+ * @since 0.1
 103+ *
 104+ * @param string $message
 105+ */
 106+ protected function showError( $message ) {
 107+ $this->getOutput()->addHTML(
 108+ '<p class="visualClear errorbox">' . wfMsgExt( $message, 'parseinline' ) . '</p>'
 109+ );
 110+ }
 111+
 112+ /**
 113+ * Show a message in a warning box.
 114+ *
 115+ * @since 0.1
 116+ *
 117+ * @param string $message
 118+ */
 119+ protected function showWarning( $message ) {
 120+ $this->getOutput()->addHTML(
 121+ '<p class="visualClear warningbox">' . wfMsgExt( $message, 'parseinline' ) . '</p>'
 122+ );
 123+ }
 124+
 125+ /**
 126+ * Display navigation links.
 127+ *
 128+ * @since 0.1
 129+ *
 130+ * @param array $links
 131+ */
 132+ protected function displayNavigation( array $links ) {
 133+ $this->getOutput()->addHTML( Html::rawElement( 'p', array(), $this->getLang()->pipeList( $links ) ) );
 134+ }
 135+
 136+}
Property changes on: tags/extensions/Survey/REL_0_1_2/specials/SpecialSurveyPage.php
___________________________________________________________________
Added: svn:eol-style
1137 + native
Index: tags/extensions/Survey/REL_0_1_2/specials/SpecialSurveyStats.php
@@ -0,0 +1,267 @@
 2+<?php
 3+
 4+/**
 5+ * Statistics interface for surveys.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SpecialSurveyStats.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SpecialSurveyStats extends SpecialSurveyPage {
 16+
 17+ /**
 18+ * Constructor.
 19+ *
 20+ * @since 0.1
 21+ */
 22+ public function __construct() {
 23+ parent::__construct( 'SurveyStats', 'surveyadmin', false );
 24+ }
 25+
 26+ /**
 27+ * Main method.
 28+ *
 29+ * @since 0.1
 30+ *
 31+ * @param string $arg
 32+ */
 33+ public function execute( $subPage ) {
 34+ if ( !parent::execute( $subPage ) ) {
 35+ return;
 36+ }
 37+
 38+ if ( is_null( $subPage ) || trim( $subPage ) === '' ) {
 39+ $this->getOutput()->redirect( SpecialPage::getTitleFor( 'Surveys' )->getLocalURL() );
 40+ } else {
 41+ $subPage = trim( $subPage );
 42+
 43+ if ( Survey::has( array( 'name' => $subPage ) ) ) {
 44+ $survey = Survey::newFromName( $subPage );
 45+
 46+ $this->displayNavigation( array(
 47+ wfMsgExt( 'survey-navigation-edit', 'parseinline', $survey->getField( 'name' ) ),
 48+ wfMsgExt( 'survey-navigation-take', 'parseinline', $survey->getField( 'name' ) ),
 49+ wfMsgExt( 'survey-navigation-list', 'parseinline' )
 50+ ) );
 51+
 52+ $this->displayStats( $survey );
 53+ }
 54+ else {
 55+ $this->showError( 'surveys-surveystats-nosuchsurvey' );
 56+ }
 57+ }
 58+ }
 59+
 60+ /**
 61+ * Display the statistics that go with the survey.
 62+ *
 63+ * @since 0.1
 64+ *
 65+ * @param Survey $survey
 66+ */
 67+ protected function displayStats( Survey $survey ) {
 68+ $this->displaySummary( $this->getSummaryData( $survey ) );
 69+
 70+ if ( count( $survey->getQuestions() ) > 0 ) {
 71+ $this->displayQuestions( $survey );
 72+ }
 73+ }
 74+
 75+ /**
 76+ * Gets the summary data.
 77+ *
 78+ * @since 0.1
 79+ *
 80+ * @param Survey $survey
 81+ *
 82+ * @return array
 83+ */
 84+ protected function getSummaryData( Survey $survey ) {
 85+ $stats = array();
 86+
 87+ $stats['name'] = $survey->getField( 'name' );
 88+ $stats['title'] = $survey->getField( 'title' );
 89+ $stats['status'] = wfMsg( 'surveys-surveystats-' . ( $survey->getField( 'enabled' ) ? 'enabled' : 'disabled' ) );
 90+ $stats['questioncount'] = count( $survey->getQuestions() ) ;
 91+ $stats['submissioncount'] = SurveySubmission::count( array( 'survey_id' => $survey->getId() ) );
 92+
 93+ return $stats;
 94+ }
 95+
 96+ /**
 97+ * Display a summary table with the provided data.
 98+ * The keys are messages that get prepended with surveys-surveystats-.
 99+ * message => value
 100+ *
 101+ * @since 0.1
 102+ *
 103+ * @param array $stats
 104+ */
 105+ protected function displaySummary( array $stats ) {
 106+ $out = $this->getOutput();
 107+
 108+ $out->addHTML( Html::openElement( 'table', array( 'class' => 'wikitable survey-stats' ) ) );
 109+
 110+ foreach ( $stats as $stat => $value ) {
 111+ $out->addHTML( '<tr>' );
 112+
 113+ $out->addHTML( Html::element(
 114+ 'th',
 115+ array( 'class' => 'survey-stat-name' ),
 116+ wfMsg( 'surveys-surveystats-' . $stat )
 117+ ) );
 118+
 119+ $out->addHTML( Html::element(
 120+ 'td',
 121+ array( 'class' => 'survey-stat-value' ),
 122+ $value
 123+ ) );
 124+
 125+ $out->addHTML( '</tr>' );
 126+ }
 127+
 128+ $out->addHTML( Html::closeElement( 'table' ) );
 129+ }
 130+
 131+ /**
 132+ * Displays a table with the surveys questions and some summary stats about them.
 133+ *
 134+ * @since 0.1
 135+ *
 136+ * @param Survey $survey
 137+ */
 138+ protected function displayQuestions( Survey $survey ) {
 139+ $out = $this->getOutput();
 140+
 141+ $out->addHTML( '<h2>' . wfMsgHtml( 'surveys-surveystats-questions' ) . '</h2>' );
 142+
 143+ $out->addHTML( Html::openElement( 'table', array( 'class' => 'wikitable sortable survey-questions' ) ) );
 144+
 145+ $out->addHTML(
 146+ '<thead><tr>' .
 147+ '<th>' . wfMsgHtml( 'surveys-surveystats-question-nr' ) . '</th>' .
 148+ '<th>' . wfMsgHtml( 'surveys-surveystats-question-type' ) . '</th>' .
 149+ '<th class="unsortable">' . wfMsgHtml( 'surveys-surveystats-question-text' ) . '</th>' .
 150+ '<th>' . wfMsgHtml( 'surveys-surveystats-question-answercount' ) . '</th>' .
 151+ '<th class="unsortable">' . wfMsgHtml( 'surveys-surveystats-question-answers' ) . '</th>' .
 152+ '</tr></thead>'
 153+ );
 154+
 155+ $out->addHTML( '<tbody>' );
 156+
 157+ foreach ( $survey->getQuestions() as /* SurveyQuestion */ $question ) {
 158+ $this->displayQuestionStats( $question );
 159+ }
 160+
 161+ $out->addHTML( '</tbody>' );
 162+
 163+ $out->addHTML( Html::closeElement( 'table' ) );
 164+ }
 165+
 166+ /**
 167+ * Adds a table row with the summary stats for the provided question.
 168+ *
 169+ * @since 0.1
 170+ *
 171+ * @param SurveyQuestion $question
 172+ */
 173+ protected function displayQuestionStats( SurveyQuestion $question ) {
 174+ static $qNr = 0;
 175+
 176+ $out = $this->getOutput();
 177+
 178+ $out->addHTML( '<tr>' );
 179+
 180+ $out->addHTML( Html::element(
 181+ 'td',
 182+ array( 'data-sort-value' => ++$qNr ),
 183+ wfMsgExt( 'surveys-surveystats-question-#', 'parsemag', $qNr )
 184+ ) );
 185+
 186+ $out->addHTML( Html::element(
 187+ 'td',
 188+ array(),
 189+ wfMsg( SurveyQuestion::getTypeMessage( $question->getField( 'type' ) ) )
 190+ ) );
 191+
 192+ $out->addHTML( Html::element(
 193+ 'td',
 194+ array(),
 195+ $question->getField( 'text' )
 196+ ) );
 197+
 198+ $out->addHTML( Html::element(
 199+ 'td',
 200+ array(),
 201+ SurveyAnswer::count( array( 'question_id' => $question->getId() ) )
 202+ ) );
 203+
 204+ $out->addHTML( Html::rawElement(
 205+ 'td',
 206+ array(),
 207+ $this->getAnswerList( $question )
 208+ ) );
 209+
 210+ $out->addHTML( '</tr>' );
 211+ }
 212+
 213+ /**
 214+ * Get a list of most provided answers for the question.
 215+ *
 216+ * @since 0.1
 217+ *
 218+ * @param SurveyQuestion $question
 219+ *
 220+ * @return string
 221+ */
 222+ protected function getAnswerList( SurveyQuestion $question ) {
 223+ if ( $question->isRestrictiveType() ) {
 224+ $list = '<ul>';
 225+
 226+ $answers = array();
 227+ $answerTranslations = array();
 228+
 229+ if ( $question->getField( 'type' ) == SurveyQuestion::$TYPE_CHECK ) {
 230+ $possibilities = array( '0', '1' );
 231+ $answerTranslations['0'] = wfMsg( 'surveys-surveystats-unchecked' );
 232+ $answerTranslations['1'] = wfMsg( 'surveys-surveystats-checked' );
 233+ }
 234+ else {
 235+ $possibilities = $question->getField( 'answers' );
 236+ }
 237+
 238+ foreach ( $possibilities as $answer ) {
 239+ $answers[$answer] = SurveyAnswer::count( array( 'text' => $answer ) );
 240+ }
 241+
 242+ asort( $answers, SORT_NUMERIC );
 243+
 244+ foreach ( array_reverse( $answers ) as $answer => $answerCount ) {
 245+ if ( array_key_exists( $answer, $answerTranslations ) ) {
 246+ $answer = $answerTranslations[$answer];
 247+ }
 248+
 249+ $list .= Html::element(
 250+ 'li',
 251+ array(),
 252+ wfMsgExt(
 253+ 'surveys-surveystats-question-answer',
 254+ 'parsemag',
 255+ $answer,
 256+ $this->getLang()->formatNum( $answerCount )
 257+ )
 258+ );
 259+ }
 260+
 261+ return $list . '</ul>';
 262+ }
 263+ else {
 264+ return '';
 265+ }
 266+ }
 267+
 268+}
Property changes on: tags/extensions/Survey/REL_0_1_2/specials/SpecialSurveyStats.php
___________________________________________________________________
Added: svn:eol-style
1269 + native
Index: tags/extensions/Survey/REL_0_1_2/specials/SpecialSurvey.php
@@ -0,0 +1,372 @@
 2+<?php
 3+
 4+/**
 5+ * Administration interface for a survey.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SpecialSurvey.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SpecialSurvey extends SpecialSurveyPage {
 16+
 17+ /**
 18+ * Constructor.
 19+ *
 20+ * @since 0.1
 21+ */
 22+ public function __construct() {
 23+ parent::__construct( 'EditSurvey', 'surveyadmin', false );
 24+ }
 25+
 26+ /**
 27+ * Main method.
 28+ *
 29+ * @since 0.1
 30+ *
 31+ * @param string $arg
 32+ */
 33+ public function execute( $subPage ) {
 34+ if ( !parent::execute( $subPage ) ) {
 35+ return;
 36+ }
 37+
 38+ global $wgRequest, $wgUser;
 39+
 40+ if ( $wgRequest->wasPosted() && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
 41+ $this->handleSubmission();
 42+ } else {
 43+ if ( is_null( $subPage ) || trim( $subPage ) === '' ) {
 44+ $this->getOutput()->redirect( SpecialPage::getTitleFor( 'Surveys' )->getLocalURL() );
 45+ } else {
 46+ $subPage = trim( $subPage );
 47+
 48+ $survey = Survey::newFromName( $subPage, null, true );
 49+
 50+ if ( $survey === false ) {
 51+ $survey = new Survey( array( 'name' => $subPage ), true );
 52+ }
 53+ else {
 54+ $this->displayNavigation( array(
 55+ wfMsgExt( 'survey-navigation-take', 'parseinline', $subPage ),
 56+ wfMsgExt( 'survey-navigation-stats', 'parseinline', $subPage ),
 57+ wfMsgExt( 'survey-navigation-list', 'parseinline' )
 58+ ) );
 59+ }
 60+
 61+ $this->showSurvey( $survey );
 62+ $this->addModules( 'ext.survey.special.survey' );
 63+ }
 64+ }
 65+ }
 66+
 67+ /**
 68+ * Handle submission of a survey.
 69+ * This conists of finding the posted survey data, constructing the
 70+ * corresponding objects, writing these to the db and then redirecting
 71+ * the user back to the surveys list.
 72+ *
 73+ * @since 0.1
 74+ */
 75+ protected function handleSubmission() {
 76+ global $wgRequest;
 77+
 78+ $values = $wgRequest->getValues();
 79+
 80+ if ( $wgRequest->getInt( 'survey-id' ) == 0 ) {
 81+ $survey = new Survey( null );
 82+ } else {
 83+ $survey = Survey::newFromId( $wgRequest->getInt( 'survey-id' ), null, false );
 84+ }
 85+
 86+ foreach ( array( 'name', 'title', 'header', 'footer', 'thanks' ) as $field ) {
 87+ $survey->setField( $field, $wgRequest->getText( 'survey-' . $field ) );
 88+ }
 89+
 90+ $survey->setField( 'enabled', $wgRequest->getCheck( 'survey-enabled' ) );
 91+
 92+ foreach ( array( 'user_type', 'ratio', 'min_pages', 'expiry' ) as $field ) {
 93+ $survey->setField( $field, $wgRequest->getInt( 'survey-' . $field ) );
 94+ }
 95+
 96+ $survey->setField( 'namespaces', array() );
 97+
 98+ $survey->setQuestions( $this->getSubmittedQuestions() );
 99+
 100+ $survey->writeToDB();
 101+
 102+ $this->getOutput()->redirect( SpecialPage::getTitleFor( 'Surveys' )->getLocalURL() );
 103+ }
 104+
 105+ /**
 106+ * Gets a list of submitted surveys.
 107+ *
 108+ * @return array of SurveyQuestion
 109+ */
 110+ protected function getSubmittedQuestions() {
 111+ $questions = array();
 112+
 113+ foreach ( $GLOBALS['wgRequest']->getValues() as $name => $value ) {
 114+ $matches = array();
 115+
 116+ if ( preg_match( '/survey-question-text-(\d+)/', $name, $matches ) ) {
 117+ $questions[] = $this->getSubmittedQuestion( $matches[1] );
 118+ } elseif ( preg_match( '/survey-question-text-new-(\d+)/', $name, $matches ) ) {
 119+ $questions[] = $this->getSubmittedQuestion( $matches[1], true );
 120+ }
 121+ }
 122+
 123+ return $questions;
 124+ }
 125+
 126+ /**
 127+ * Create and return a survey question object from the submitted data.
 128+ *
 129+ * @since 0.1
 130+ *
 131+ * @param integer|null $questionId
 132+ *
 133+ * @return SurveyQuestion
 134+ */
 135+ protected function getSubmittedQuestion( $questionId, $isNewQuestion = false ) {
 136+ global $wgRequest;
 137+
 138+ if ( $isNewQuestion ) {
 139+ $questionDbId = null;
 140+ $questionId = "new-$questionId";
 141+ } else {
 142+ $questionDbId = $questionId;
 143+ }
 144+
 145+ $answers = array_filter(
 146+ explode( "\n", $wgRequest->getText( "survey-question-answers-$questionId" ) ),
 147+ function( $line ) {
 148+ return trim( $line ) != '';
 149+ }
 150+ );
 151+
 152+ $question = new SurveyQuestion( array(
 153+ 'id' => $questionDbId,
 154+ 'removed' => 0,
 155+ 'text' => $wgRequest->getText( "survey-question-text-$questionId" ),
 156+ 'type' => $wgRequest->getInt( "survey-question-type-$questionId" ),
 157+ 'required' => 0, // $wgRequest->getCheck( "survey-question-required-$questionId" ),
 158+ 'answers' => $answers
 159+ ) );
 160+
 161+ return $question;
 162+ }
 163+
 164+ /**
 165+ * Show error when requesting a non-existing survey.
 166+ *
 167+ * @since 0.1
 168+ */
 169+ protected function showNameError() {
 170+ $this->getOutput()->addHTML(
 171+ '<p class="errorbox">' . wfMsgHtml( 'surveys-special-unknown-name' ) . '</p>'
 172+ );
 173+ }
 174+
 175+ /**
 176+ * Get an array of numbers with as keys the formatted version of the values.
 177+ *
 178+ * @since 0.1
 179+ *
 180+ * @param array $numbers
 181+ *
 182+ * @return array
 183+ */
 184+ protected function getNumericalOptions( array $numbers ) {
 185+ $lang = $this->getLang();
 186+
 187+ return array_flip( array_map(
 188+ function( $n ) use( $lang ) { return $lang->formatNum( $n ); },
 189+ array_combine( $numbers, $numbers )
 190+ ) );
 191+ }
 192+
 193+ /**
 194+ * Show the survey.
 195+ *
 196+ * @since 0.1
 197+ *
 198+ * @param Survey $survey
 199+ */
 200+ protected function showSurvey( Survey $survey ) {
 201+ $fields = array();
 202+
 203+ $fields[] = array(
 204+ 'type' => 'hidden',
 205+ 'default' => $survey->getId(),
 206+ 'name' => 'survey-id',
 207+ 'id' => 'survey-id',
 208+ );
 209+
 210+ $fields[] = array(
 211+ 'type' => 'hidden',
 212+ 'default' => $survey->getField( 'name' ),
 213+ 'name' => 'survey-name',
 214+ 'id' => 'survey-name',
 215+ );
 216+
 217+ $fields[] = array(
 218+ 'type' => 'hidden',
 219+ 'default' => $survey->getField( 'expiry' ),
 220+ 'name' => 'survey-expiry',
 221+ 'id' => 'survey-expiry',
 222+ );
 223+
 224+ $fields[] = array(
 225+ 'class' => 'SurveyNameField',
 226+ 'default' => $survey->getField( 'name' ),
 227+ 'label-message' => 'survey-special-label-name',
 228+ 'style' => 'font-weight: bold;'
 229+ );
 230+
 231+ $fields[] = array(
 232+ 'type' => 'text',
 233+ 'default' => $survey->getField( 'title' ),
 234+ 'label-message' => 'survey-special-label-title',
 235+ 'id' => 'survey-title',
 236+ 'name' => 'survey-title',
 237+ );
 238+
 239+ $fields[] = array(
 240+ 'type' => 'check',
 241+ 'default' => $survey->getField( 'enabled' ) ? '1' : '0',
 242+ 'label-message' => 'survey-special-label-enabled',
 243+ 'id' => 'survey-enabled',
 244+ 'name' => 'survey-enabled',
 245+ );
 246+
 247+ $fields[] = array(
 248+ 'type' => 'radio',
 249+ 'default' => $survey->getField( 'user_type' ),
 250+ 'label-message' => 'survey-special-label-usertype',
 251+ 'id' => 'survey-user_type',
 252+ 'name' => 'survey-user_type',
 253+ 'options' => array(
 254+ wfMsg( 'survey-user-type-all' ) => Survey::$USER_ALL,
 255+ wfMsg( 'survey-user-type-loggedin' ) => Survey::$USER_LOGGEDIN,
 256+ wfMsg( 'survey-user-type-confirmed' ) => Survey::$USER_CONFIRMED,
 257+ wfMsg( 'survey-user-type-editor' ) => Survey::$USER_EDITOR,
 258+ wfMsg( 'survey-user-type-anon' ) => Survey::$USER_ANON,
 259+ ),
 260+ );
 261+
 262+ $fields[] = array(
 263+ 'type' => 'select',
 264+ 'default' => $survey->getField( 'ratio' ),
 265+ 'label-message' => 'survey-special-label-ratio',
 266+ 'id' => 'survey-ratio',
 267+ 'name' => 'survey-ratio',
 268+ 'options' => $this->getNumericalOptions( array_merge( array( 0.01, 0.1 ), range( 1, 100 ) ) ),
 269+ );
 270+
 271+ $fields[] = array(
 272+ 'type' => 'select',
 273+ 'default' => $survey->getField( 'min_pages' ),
 274+ 'label-message' => 'survey-special-label-minpages',
 275+ 'id' => 'survey-min_pages',
 276+ 'name' => 'survey-min_pages',
 277+ 'options' => $this->getNumericalOptions( range( 0, 250 ) ),
 278+ );
 279+
 280+ $fields[] = array(
 281+ 'type' => 'text',
 282+ 'default' => $survey->getField( 'header' ),
 283+ 'label-message' => 'survey-special-label-header',
 284+ 'id' => 'survey-header',
 285+ 'name' => 'survey-header',
 286+ );
 287+
 288+ $fields[] = array(
 289+ 'type' => 'text',
 290+ 'default' => $survey->getField( 'footer' ),
 291+ 'label-message' => 'survey-special-label-footer',
 292+ 'id' => 'survey-footer',
 293+ 'name' => 'survey-footer',
 294+ );
 295+
 296+ $fields[] = array(
 297+ 'type' => 'text',
 298+ 'default' => $survey->getField( 'thanks' ),
 299+ 'label-message' => 'survey-special-label-thanks',
 300+ 'id' => 'survey-thanks',
 301+ 'name' => 'survey-thanks',
 302+ );
 303+
 304+ foreach ( $survey->getQuestions() as /* SurveyQuestion */ $question ) {
 305+ $fields[] = array(
 306+ 'class' => 'SurveyQuestionField',
 307+ 'options' => $question->toArray()
 308+ );
 309+ }
 310+
 311+ // getContext was added in 1.18 and since that version is
 312+ // the second argument for the HTMLForm constructor.
 313+ if ( version_compare( $GLOBALS['wgVersion'], '1.18', '>=' ) ) {
 314+ $form = new HTMLForm( $fields, $this->getContext() );
 315+ } else {
 316+ $form = new HTMLForm( $fields );
 317+ $form->setTitle( $this->getTitle() );
 318+ }
 319+
 320+ $form->setSubmitText( wfMsg( 'surveys-special-save' ) );
 321+
 322+ $form->addButton(
 323+ 'cancelEdit',
 324+ wfMsg( 'cancel' ),
 325+ 'cancelEdit',
 326+ array(
 327+ 'onclick' => 'window.location="' . SpecialPage::getTitleFor( 'Surveys' )->getFullURL() . '";return false;'
 328+ )
 329+ );
 330+
 331+ $form->show();
 332+ }
 333+
 334+}
 335+
 336+class SurveyQuestionField extends HTMLFormField {
 337+
 338+ public function getInputHTML( $value ) {
 339+ $attribs = array(
 340+ 'class' => 'survey-question-data'
 341+ );
 342+
 343+ foreach ( $this->mParams['options'] as $name => $value ) {
 344+ if ( is_bool( $value ) ) {
 345+ $value = $value ? '1' : '0';
 346+ } elseif( is_object( $value ) || is_array( $value ) ) {
 347+ $value = FormatJson::encode( $value );
 348+ }
 349+
 350+ $attribs['data-' . $name] = $value;
 351+ }
 352+
 353+ return Html::element(
 354+ 'div',
 355+ $attribs
 356+ );
 357+ }
 358+
 359+}
 360+
 361+class SurveyNameField extends HTMLFormField {
 362+
 363+ public function getInputHTML( $value ) {
 364+ return Html::element(
 365+ 'span',
 366+ array(
 367+ 'style' => $this->mParams['style']
 368+ ),
 369+ $value
 370+ );
 371+ }
 372+
 373+}
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/specials/SpecialSurvey.php
___________________________________________________________________
Added: svn:eol-style
1374 + native
Index: tags/extensions/Survey/REL_0_1_2/specials/SpecialSurveys.php
@@ -0,0 +1,183 @@
 2+<?php
 3+
 4+/**
 5+ * Administration interface for surveys.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SpecialSurveys.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SpecialSurveys extends SpecialSurveyPage {
 16+
 17+ /**
 18+ * Constructor.
 19+ *
 20+ * @since 0.1
 21+ */
 22+ public function __construct() {
 23+ parent::__construct( 'Surveys', 'surveyadmin' );
 24+ }
 25+
 26+ /**
 27+ * Main method.
 28+ *
 29+ * @since 0.1
 30+ *
 31+ * @param string $arg
 32+ */
 33+ public function execute( $subPage ) {
 34+ if ( !parent::execute( $subPage ) ) {
 35+ return;
 36+ }
 37+
 38+ global $wgRequest, $wgUser;
 39+
 40+ if ( $wgRequest->wasPosted()
 41+ && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) )
 42+ && $wgRequest->getCheck( 'newsurvey' ) ) {
 43+ $this->getOutput()->redirect( SpecialPage::getTitleFor( 'EditSurvey', $wgRequest->getVal( 'newsurvey' ) )->getLocalURL() );
 44+ } else {
 45+ $this->displaySurveys();
 46+ }
 47+ }
 48+
 49+ /**
 50+ * Displays surveys.
 51+ *
 52+ * @since 0.1
 53+ */
 54+ protected function displaySurveys() {
 55+ $this->displayAddNewControl();
 56+
 57+ $surveys = Survey::select( array( 'id', 'name', 'enabled', 'title' ) );
 58+
 59+ if ( count( $surveys ) > 0 ) {
 60+ $this->displaySurveysTable( $surveys );
 61+ }
 62+
 63+ $this->addModules( 'ext.survey.special.surveys' );
 64+ }
 65+
 66+ /**
 67+ * Displays a small form to add a new campaign.
 68+ *
 69+ * @since 0.1
 70+ */
 71+ protected function displayAddNewControl() {
 72+ $out = $this->getOutput();
 73+
 74+ $out->addHTML( Html::openElement(
 75+ 'form',
 76+ array(
 77+ 'method' => 'post',
 78+ 'action' => $this->getTitle()->getLocalURL(),
 79+ )
 80+ ) );
 81+
 82+ $out->addHTML( '<fieldset>' );
 83+
 84+ $out->addHTML( '<legend>' . htmlspecialchars( wfMsg( 'surveys-special-addnew' ) ) . '</legend>' );
 85+
 86+ $out->addHTML( Html::element( 'p', array(), wfMsg( 'surveys-special-namedoc' ) ) );
 87+
 88+ $out->addHTML( Html::element( 'label', array( 'for' => 'newcampaign' ), wfMsg( 'surveys-special-newname' ) ) );
 89+
 90+ $out->addHTML( '&#160;' . Html::input( 'newsurvey' ) . '&#160;' );
 91+
 92+ $out->addHTML( Html::input(
 93+ 'addnewsurvey',
 94+ wfMsg( 'surveys-special-add' ),
 95+ 'submit'
 96+ ) );
 97+
 98+ global $wgUser;
 99+ $out->addHTML( Html::hidden( 'wpEditToken', $wgUser->editToken() ) );
 100+
 101+ $out->addHTML( '</fieldset></form>' );
 102+ }
 103+
 104+ /**
 105+ * Displays a list of all survets.
 106+ *
 107+ * @since 0.1
 108+ *
 109+ * @param array $surveys
 110+ */
 111+ protected function displaySurveysTable( array /* of Survey */ $surveys ) {
 112+ $out = $this->getOutput();
 113+
 114+ $out->addHTML( Html::element( 'h2', array(), wfMsg( 'surveys-special-existing' ) ) );
 115+
 116+ $out->addHTML( Xml::openElement(
 117+ 'table',
 118+ array( 'class' => 'wikitable sortable' )
 119+ ) );
 120+
 121+ $out->addHTML(
 122+ '<thead><tr>' .
 123+ Html::element( 'th', array(), wfMsg( 'surveys-special-title' ) ) .
 124+ Html::element( 'th', array(), wfMsg( 'surveys-special-status' ) ) .
 125+ Html::element( 'th', array( 'class' => 'unsortable' ), wfMsg( 'surveys-special-stats' ) ) .
 126+ Html::element( 'th', array( 'class' => 'unsortable' ), wfMsg( 'surveys-special-edit' ) ) .
 127+ Html::element( 'th', array( 'class' => 'unsortable' ), wfMsg( 'surveys-special-delete' ) ) .
 128+ '</tr></thead>'
 129+ );
 130+
 131+ $out->addHTML( '<tbody>' );
 132+
 133+ foreach ( $surveys as $survey ) {
 134+ $out->addHTML(
 135+ '<tr>' .
 136+ '<td data-sort-value="' . htmlspecialchars( $survey->getField( 'title' ) ) . '">' .
 137+ Html::element(
 138+ 'a',
 139+ array(
 140+ 'href' => SpecialPage::getTitleFor( 'TakeSurvey', $survey->getField( 'name' ) )->getLocalURL()
 141+ ),
 142+ $survey->getField( 'title' )
 143+ ) .
 144+ '</td>' .
 145+ Html::element( 'td', array(), wfMsg( 'surveys-special-' . ( $survey->getField( 'enabled' ) ? 'enabled' : 'disabled' ) ) ) .
 146+ '<td>' .
 147+ Html::element(
 148+ 'a',
 149+ array(
 150+ 'href' => SpecialPage::getTitleFor( 'SurveyStats', $survey->getField( 'name' ) )->getLocalURL()
 151+ ),
 152+ wfMsg( 'surveys-special-stats' )
 153+ ) .
 154+ '</td>' .
 155+ '<td>' .
 156+ Html::element(
 157+ 'a',
 158+ array(
 159+ 'href' => SpecialPage::getTitleFor( 'EditSurvey', $survey->getField( 'name' ) )->getLocalURL()
 160+ ),
 161+ wfMsg( 'surveys-special-edit' )
 162+ ) .
 163+ '</td>' .
 164+ '<td>' .
 165+ Html::element(
 166+ 'a',
 167+ array(
 168+ 'href' => '#',
 169+ 'class' => 'survey-delete',
 170+ 'data-survey-id' => $survey->getId(),
 171+ 'data-survey-token' => $GLOBALS['wgUser']->editToken( 'deletesurvey' . $survey->getId() )
 172+ ),
 173+ wfMsg( 'surveys-special-delete' )
 174+ ) .
 175+ '</td>' .
 176+ '</tr>'
 177+ );
 178+ }
 179+
 180+ $out->addHTML( '</tbody>' );
 181+ $out->addHTML( '</table>' );
 182+ }
 183+
 184+}
Property changes on: tags/extensions/Survey/REL_0_1_2/specials/SpecialSurveys.php
___________________________________________________________________
Added: svn:eol-style
1185 + native
Index: tags/extensions/Survey/REL_0_1_2/specials/SpecialTakeSurvey.php
@@ -0,0 +1,84 @@
 2+<?php
 3+
 4+/**
 5+ * Page on which a survey is displayed.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SpecialTakeSurvey.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SpecialTakeSurvey extends SpecialSurveyPage {
 16+
 17+ /**
 18+ * Constructor.
 19+ *
 20+ * @since 0.1
 21+ */
 22+ public function __construct() {
 23+ parent::__construct( 'TakeSurvey', 'surveysubmit' );
 24+ }
 25+
 26+ /**
 27+ * Main method.
 28+ *
 29+ * @since 0.1
 30+ *
 31+ * @param string $arg
 32+ */
 33+ public function execute( $subPage ) {
 34+ if ( !parent::execute( $subPage ) ) {
 35+ return;
 36+ }
 37+
 38+ $survey = Survey::selectRow(
 39+ array( 'enabled' ),
 40+ array( 'name' => $subPage )
 41+ );
 42+
 43+ if ( $survey === false ) {
 44+ $this->showError( 'surveys-takesurvey-nosuchsurvey' );
 45+ }
 46+ else if ( $survey->getField( 'enabled' ) ) {
 47+ $this->displaySurvey( $subPage );
 48+ }
 49+ else if ( $GLOBALS['wgUser']->isAllowed( 'surveyadmin' ) ) {
 50+ $this->showWarning( 'surveys-takesurvey-warn-notenabled' );
 51+ $this->getOutput()->addHTML( '<br /><br /><br /><br />' );
 52+ $this->displaySurvey( $subPage );
 53+ }
 54+ else {
 55+ $this->showError( 'surveys-takesurvey-surveynotenabled' );
 56+ }
 57+ }
 58+
 59+ /**
 60+ * Add the output for the actual survey.
 61+ * This is done by adding a survey tag as wikitext, which then get's rendered.
 62+ *
 63+ * @since 0.1
 64+ *
 65+ * @param string $subPage
 66+ */
 67+ protected function displaySurvey( $subPage ) {
 68+ $this->displayNavigation( array(
 69+ wfMsgExt( 'survey-navigation-edit', 'parseinline', $subPage ),
 70+ wfMsgExt( 'survey-navigation-stats', 'parseinline', $subPage ),
 71+ wfMsgExt( 'survey-navigation-list', 'parseinline' )
 72+ ) );
 73+
 74+ $this->getOutput()->addWikiText( Xml::element(
 75+ 'survey',
 76+ array(
 77+ 'name' => $subPage,
 78+ 'require-enabled' => $GLOBALS['wgUser']->isAllowed( 'surveyadmin' ) ? '0' : '1',
 79+ 'cookie' => 'no'
 80+ ),
 81+ wfMsg( 'surveys-takesurvey-loading' )
 82+ ) );
 83+ }
 84+
 85+}
Property changes on: tags/extensions/Survey/REL_0_1_2/specials/SpecialTakeSurvey.php
___________________________________________________________________
Added: svn:eol-style
186 + native
Index: tags/extensions/Survey/REL_0_1_2/Survey.hooks.php
@@ -0,0 +1,188 @@
 2+<?php
 3+
 4+/**
 5+ * Static class for hooks handled by the Survey extension.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file Survey.hooks.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3+
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+final class SurveyHooks {
 16+
 17+ /**
 18+ * Register the survey tag extension when the parser initializes.
 19+ *
 20+ * @since 0.1
 21+ *
 22+ * @param Parser $parser
 23+ *
 24+ * @return true
 25+ */
 26+ public static function onParserFirstCallInit( Parser &$parser ) {
 27+ $parser->setHook( 'survey', __CLASS__ . '::onSurveyRender' );
 28+ return true;
 29+ }
 30+
 31+ /**
 32+ * Render the survey tag.
 33+ *
 34+ * @since 0.1
 35+ *
 36+ * @param mixed $input
 37+ * @param array $args
 38+ * @param Parser $parser
 39+ * @param PPFrame $frame
 40+ */
 41+ public static function onSurveyRender( $input, array $args, Parser $parser, PPFrame $frame ) {
 42+ $tag = new SurveyTag( $args, $input );
 43+ return $tag->render( $parser );
 44+ }
 45+
 46+ /**
 47+ * Schema update to set up the needed database tables.
 48+ *
 49+ * @since 0.1
 50+ *
 51+ * @param DatabaseUpdater $updater
 52+ *
 53+ * @return true
 54+ */
 55+ public static function onSchemaUpdate( /* DatabaseUpdater */ $updater = null ) {
 56+ global $wgDBtype;
 57+
 58+ $updater->addExtensionUpdate( array(
 59+ 'addTable',
 60+ 'surveys',
 61+ dirname( __FILE__ ) . '/Survey.sql',
 62+ true
 63+ ) );
 64+ $updater->addExtensionUpdate( array(
 65+ 'addTable',
 66+ 'survey_questions',
 67+ dirname( __FILE__ ) . '/Survey.sql',
 68+ true
 69+ ) );
 70+ $updater->addExtensionUpdate( array(
 71+ 'addTable',
 72+ 'survey_submissions',
 73+ dirname( __FILE__ ) . '/Survey.sql',
 74+ true
 75+ ) );
 76+ $updater->addExtensionUpdate( array(
 77+ 'addTable',
 78+ 'survey_answers',
 79+ dirname( __FILE__ ) . '/Survey.sql',
 80+ true
 81+ ) );
 82+ $updater->addExtensionUpdate( array(
 83+ 'addIndex',
 84+ 'surveys',
 85+ 'surveys_survey_name',
 86+ dirname( __FILE__ ) . '/sql/Survey_indexSurveyName.sql',
 87+ true
 88+ ) );
 89+ $updater->addExtensionUpdate( array(
 90+ 'addIndex',
 91+ 'survey_answers',
 92+ 'surveys_question_id',
 93+ dirname( __FILE__ ) . '/sql/Survey_indexQuestionId.sql',
 94+ true
 95+ ) );
 96+ $updater->addExtensionUpdate( array(
 97+ 'addIndex',
 98+ 'survey_answers',
 99+ 'surveys_submission_id',
 100+ dirname( __FILE__ ) . '/sql/Survey_indexSubmissionId.sql',
 101+ true
 102+ ) );
 103+
 104+ return true;
 105+ }
 106+
 107+ /**
 108+ * Hook to add PHPUnit test cases.
 109+ *
 110+ * @since 0.1
 111+ *
 112+ * @param array $files
 113+ */
 114+ public static function registerUnitTests( array &$files ) {
 115+ $testDir = dirname( __FILE__ ) . '/test/';
 116+
 117+ $files[] = $testDir . 'SurveyQuestionTest.php';
 118+
 119+ return true;
 120+ }
 121+
 122+ /**
 123+ * Hook to insert things into article headers.
 124+ *
 125+ * @since 0.1
 126+ *
 127+ * @param Article &$article
 128+ * @param boolean $outputDone
 129+ * @param boolean $useParserCache
 130+ *
 131+ * @return true
 132+ */
 133+ public static function onArticleViewHeader( Article &$article, &$outputDone, &$useParserCache ) {
 134+ if ( !Survey::has( array( 'enabled' => 1 ) ) ) {
 135+ return true;
 136+ }
 137+
 138+ $surveys = Survey::select(
 139+ array(
 140+ 'id', 'namespaces', 'ratio', 'expiry', 'min_pages'
 141+ ),
 142+ array(
 143+ 'enabled' => 1,
 144+ 'user_type' => Survey::getTypesForUser( $GLOBALS['wgUser'] )
 145+ )
 146+ );
 147+
 148+ foreach ( $surveys as /* Survey */ $survey ) {
 149+
 150+ if ( count( $survey->getField( 'namespaces' ) ) == 0 ) {
 151+ $nsValid = true;
 152+ }
 153+ else {
 154+ $nsValid = in_array( $article->getTitle()->getNamespace(), $survey->getField( 'namespaces' ) );
 155+ }
 156+
 157+ if ( $nsValid ) {
 158+ $GLOBALS['wgOut']->addWikiText( Xml::element(
 159+ 'survey',
 160+ array(
 161+ 'id' => $survey->getId(),
 162+ 'ratio' => $survey->getField( 'ratio' ),
 163+ 'expiry' => $survey->getField( 'expiry' ),
 164+ 'min-pages' => $survey->getField( 'min_pages' ),
 165+ )
 166+ ) );
 167+ }
 168+ }
 169+
 170+ return true;
 171+ }
 172+
 173+ /**
 174+ * Adds a link to Admin Links page.
 175+ *
 176+ * @since 0.1
 177+ *
 178+ * @return true
 179+ */
 180+ public static function addToAdminLinks( &$admin_links_tree ) {
 181+ $section = new ALSection( 'Survey' );
 182+ $row = new ALRow( 'smw' );
 183+ $row->addItem( AlItem::newFromSpecialPage( 'Surveys' ) );
 184+ $section->addRow( $row );
 185+ $admin_links_tree->addSection( $section, 'Survey' );
 186+ return true;
 187+ }
 188+
 189+}
Property changes on: tags/extensions/Survey/REL_0_1_2/Survey.hooks.php
___________________________________________________________________
Added: svn:eol-style
1190 + native
Index: tags/extensions/Survey/REL_0_1_2/INSTALL
@@ -0,0 +1,85 @@
 2+This is the install file for the Survey extension.
 3+
 4+Extension page on mediawiki.org: http://www.mediawiki.org/wiki/Extension:Survey
 5+Latest version of the install file: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Survey/INSTALL?view=co
 6+
 7+
 8+== Requirements ==
 9+
 10+Survey requires:
 11+
 12+* MediaWiki 1.17 or above
 13+* PHP 5.3 or above
 14+
 15+== Download ==
 16+
 17+You can find the current version of Survey on the [https://code.google.com/p/mwsuvey/downloads/list Google Code download page],
 18+as well as a [https://code.google.com/p/mwsuvey/downloads/list?can=1 list of legacy downloads].
 19+
 20+You can also get the code directly from SVN. Tags can be obtained via
 21+
 22+ svn checkout <nowiki>http://svn.wikimedia.org/svnroot/mediawiki/tags/extensions/Survey/REL_version</nowiki>
 23+
 24+Where 'version' is the version number of the tag, such as 0_1 (see the [http://svn.wikimedia.org/svnroot/mediawiki/tags/extensions/Survey/ available tags]).
 25+The latest code can be obtained from trunk:
 26+
 27+ svn checkout <nowiki>http://svn.wikimedia.org/svnroot/mediawiki/trunk/extensions/Survey/</nowiki>
 28+
 29+== Installation ==
 30+
 31+Once you have downloaded the code, place the ''Survey'' directory within your MediaWiki
 32+'extensions' directory. Then add the following code to your [[Manual:LocalSettings.php|LocalSettings.php]] file:
 33+
 34+# Survey
 35+require_once( "$IP/extensions/Survey/Survey.php" );
 36+
 37+== Configuration ==
 38+
 39+Configuration of Survey is done by assigning to $egSurveySettings in your
 40+[[Manual:LocalSettings.php|LocalSettings.php]] file, AFTER the inlcusion of the
 41+extension. The options are listed below and their default is set in the Survey settings file:
 42+http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Survey/Survey.settings.php?view=markup
 43+You should NOT modify the settings file, but can have a look at it to get an idea of
 44+how to use the settings, in case the below descriptions do not suffice.
 45+
 46+{| class="wikitable sortable"
 47+! Name
 48+! Type
 49+! Default
 50+! Description
 51+|-
 52+| defaultEnabled
 53+| boolean
 54+| false
 55+| If surveys should be enabled by default
 56+|-
 57+| defaultUserType
 58+| Survey::$USER_
 59+| Survey::$USER_ALL
 60+| The default type of users a survey is shown to
 61+|-
 62+| defaultNamespaces
 63+| array
 64+| array()
 65+| The default namespaces in which surveys should be shown. Empty list for no namespace restrictions
 66+|-
 67+| defaultRatio
 68+| integer
 69+| 100
 70+| The default percentage of users the surveys should be shown to
 71+|-
 72+| defaultExpiry
 73+| integer
 74+| 60 * 60 * 24 * 30
 75+| The default expiry of cookies used to track survey completion of users, in seconds
 76+|-
 77+| defaultMinPages
 78+| integer
 79+| 0
 80+| The default minimun amount of pages users should visit before getting a survey
 81+| -
 82+| JSDebug
 83+| boolean
 84+| false
 85+| Indicates if JavaScript debugging should be on or not. Should be false on production environments.
 86+|}
Property changes on: tags/extensions/Survey/REL_0_1_2/INSTALL
___________________________________________________________________
Added: svn:eol-style
187 + native
Index: tags/extensions/Survey/REL_0_1_2/RELEASE-NOTES
@@ -0,0 +1,31 @@
 2+These are the release notes for the Survey extension.
 3+
 4+Extension page on mediawiki.org: http://www.mediawiki.org/wiki/Extension:Survey
 5+Latest version of the release notes: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Survey/RELEASE-NOTES?view=co
 6+
 7+
 8+=== Version 0.1.2 ===
 9+2011-11-14
 10+
 11+* Fixed issue with database index names causing update.php to fail when running after installation of Survey.
 12+* Fixed several IE JavaScript issues.
 13+* Added missing action- messages.
 14+
 15+=== Version 0.1.1 ===
 16+2011-09-18
 17+
 18+* Restricted access to survey statistics via the API to survey admins.
 19+
 20+=== Version 0.1 ===
 21+2011-09-13
 22+
 23+Initial release with these features:
 24+
 25+* Surveys get displayed to wiki users using a nice pop-up form.
 26+* Surveys can be created and modified via an admin panel (Special:Surveys).
 27+* Surveys can be shown to specific types of users (logged in, anonymous, editor, confirmed, ...)
 28+* Surveys can be shown for a specified percentage of users, and only after a certain amount of page views.
 29+* Survey questions can have different types of inputs, of which some allow restricting answers.
 30+* Surveys can be tested by admins via Special:TakeSurvey without them being live on the wiki.
 31+* Summaries of survey submissions can be found on Special:SurveyStats.
 32+* The survey submission data (ie user answers) can be exported via an API.
Property changes on: tags/extensions/Survey/REL_0_1_2/RELEASE-NOTES
___________________________________________________________________
Added: svn:eol-style
133 + native
Index: tags/extensions/Survey/REL_0_1_2/includes/SurveyDBClass.php
@@ -0,0 +1,732 @@
 2+<?php
 3+
 4+/**
 5+ * Abstract base class for representing objects that are stored in some DB table.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SurveyDBClass.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+abstract class SurveyDBClass {
 16+
 17+ /**
 18+ * The fields of the object.
 19+ * field name (w/o prefix) => value
 20+ *
 21+ * @since 0.1
 22+ * @var array
 23+ */
 24+ protected $fields = array();
 25+
 26+ /**
 27+ * Constructor.
 28+ *
 29+ * @since 0.1
 30+ *
 31+ * @param array|null $fields
 32+ * @param boolean $loadDefaults
 33+ */
 34+ public function __construct( $fields, $loadDefaults = false ) {
 35+ $this->setField( static::getIDField(), null );
 36+
 37+ if ( !is_array( $fields ) ) {
 38+ $fields = array();
 39+ }
 40+
 41+ if ( $loadDefaults ) {
 42+ $fields = array_merge( static::getDefaults(), $fields );
 43+ }
 44+
 45+ $this->setFields( $fields );
 46+ }
 47+
 48+ /**
 49+ * Returns an array with the fields and their types this object contains.
 50+ * This corresponds directly to the fields in the database, without prefix.
 51+ *
 52+ * field name => type
 53+ *
 54+ * Allowed types:
 55+ * * id
 56+ * * str
 57+ * * int
 58+ * * bool
 59+ * * array
 60+ *
 61+ * @since 0.1
 62+ *
 63+ * @return array
 64+ */
 65+ protected static function getFieldTypes() {
 66+ return array();
 67+ }
 68+
 69+ /**
 70+ * Returns an array with the fields and their descriptions.
 71+ *
 72+ * field name => field description
 73+ *
 74+ * @since 0.1
 75+ *
 76+ * @return array
 77+ */
 78+ public static function getFieldDescriptions() {
 79+ return array();
 80+ }
 81+
 82+ /**
 83+ * Returns the name of the database table objects of this type are stored in.
 84+ *
 85+ * @since 0.1
 86+ *
 87+ * @throws MWException
 88+ * @return string
 89+ */
 90+ public static function getDBTable() {
 91+ throw new MWException( 'Class did not implement getDBTable' );
 92+ }
 93+
 94+ /**
 95+ * Gets the db field prefix.
 96+ *
 97+ * @since 0.1
 98+ *
 99+ * @throws MWException
 100+ * @return string
 101+ */
 102+ protected static function getFieldPrefix() {
 103+ throw new MWException( 'Class did not implement getFieldPrefix' );
 104+ }
 105+
 106+ /**
 107+ * Returns the name of the id db field, without prefix.
 108+ *
 109+ * @since 0.1
 110+ *
 111+ * @return string
 112+ */
 113+ protected static function getIDField() {
 114+ return 'id';
 115+ }
 116+
 117+ /**
 118+ * Get a new instance of the class from a database result.
 119+ *
 120+ * @since 0.1
 121+ *
 122+ * @param object $result
 123+ *
 124+ * @return SurveyDBClass
 125+ */
 126+ public static function newFromDBResult( $result ) {
 127+ $result = (array)$result;
 128+ $data = array();
 129+ $idFieldLength = strlen( static::getFieldPrefix() );
 130+
 131+ foreach ( $result as $name => $value ) {
 132+ $data[substr( $name, $idFieldLength )] = $value;
 133+ }
 134+
 135+ return static::newFromArray( $data );
 136+ }
 137+
 138+ /**
 139+ * Get a new instance of the class from an array.
 140+ *
 141+ * @since 0.1
 142+ *
 143+ * @param array $data
 144+ * @param boolean $loadDefaults
 145+ *
 146+ * @return SurveyDBClass
 147+ */
 148+ public static function newFromArray( array $data, $loadDefaults = false ) {
 149+ return new static( $data, $loadDefaults );
 150+ }
 151+
 152+ /**
 153+ * Selects the the specified fields of the records matching the provided
 154+ * conditions. Field names get prefixed.
 155+ *
 156+ * @since 0.1
 157+ *
 158+ * @param array|null $fields
 159+ * @param array $conditions
 160+ * @param array $options
 161+ *
 162+ * @return array of self
 163+ */
 164+ public static function select( $fields = null, array $conditions = array(), array $options = array() ) {
 165+ if ( is_null( $fields ) ) {
 166+ $fields = array_keys( static::getFieldTypes() );
 167+ }
 168+
 169+ $result = static::rawSelect(
 170+ static::getPrefixedFields( $fields ),
 171+ static::getPrefixedValues( $conditions ),
 172+ $options
 173+ );
 174+
 175+ $objects = array();
 176+
 177+ foreach ( $result as $record ) {
 178+ $objects[] = static::newFromDBResult( $record );
 179+ }
 180+
 181+ return $objects;
 182+ }
 183+
 184+ /**
 185+ * Selects the the specified fields of the first matching record.
 186+ * Field names get prefixed.
 187+ *
 188+ * @since 0.1
 189+ *
 190+ * @param array|null $fields
 191+ * @param array $conditions
 192+ * @param array $options
 193+ *
 194+ * @return self|false
 195+ */
 196+ public static function selectRow( $fields = null, array $conditions = array(), array $options = array() ) {
 197+ $options['LIMIT'] = 1;
 198+
 199+ $objects = static::select( $fields, $conditions, $options );
 200+
 201+ return count( $objects ) > 0 ? $objects[0] : false;
 202+ }
 203+
 204+ /**
 205+ * Returns if there is at least one record matching the provided conditions.
 206+ * Condition field names get prefixed.
 207+ *
 208+ * @since 0.1
 209+ *
 210+ * @param array $conditions
 211+ *
 212+ * @return boolean
 213+ */
 214+ public static function has( array $conditions = array() ) {
 215+ return static::selectRow( array( static::getIDField() ), $conditions ) !== false;
 216+ }
 217+
 218+ /**
 219+ * Returns the amount of matching records.
 220+ * Condition field names get prefixed.
 221+ *
 222+ * @since 0.1
 223+ *
 224+ * @param array $conditions
 225+ * @param array $options
 226+ *
 227+ * @return integer
 228+ */
 229+ public static function count( array $conditions = array(), array $options = array() ) {
 230+ $res = static::rawSelect(
 231+ array( 'COUNT(*) AS rowcount' ),
 232+ static::getPrefixedValues( $conditions ),
 233+ $options
 234+ )->fetchObject();
 235+
 236+ return $res->rowcount;
 237+ }
 238+
 239+ /**
 240+ * Selects the the specified fields of the records matching the provided
 241+ * conditions. Field names do NOT get prefixed.
 242+ *
 243+ * @since 0.1
 244+ *
 245+ * @param array|null $fields
 246+ * @param array $conditions
 247+ * @param array $options
 248+ *
 249+ * @return ResultWrapper
 250+ */
 251+ public static function rawSelect( $fields = null, array $conditions = array(), array $options = array() ) {
 252+ $dbr = wfGetDB( DB_SLAVE );
 253+
 254+ return $dbr->select(
 255+ static::getDBTable(),
 256+ $fields,
 257+ count( $conditions ) == 0 ? '' : $conditions,
 258+ '',
 259+ $options
 260+ );
 261+ }
 262+
 263+ public static function update( array $values, array $conditions = array() ) {
 264+ $dbw = wfGetDB( DB_MASTER );
 265+
 266+ return $dbw->update(
 267+ static::getDBTable(),
 268+ static::getPrefixedValues( $values ),
 269+ static::getPrefixedValues( $conditions )
 270+ );
 271+ }
 272+
 273+ /**
 274+ * Writes the answer to the database, either updating it
 275+ * when it already exists, or inserting it when it doesn't.
 276+ *
 277+ * @since 0.1
 278+ *
 279+ * @return boolean Success indicator
 280+ */
 281+ public function writeToDB() {
 282+ if ( $this->hasIdField() ) {
 283+ return $this->updateInDB();
 284+ } else {
 285+ return $this->insertIntoDB();
 286+ }
 287+ }
 288+
 289+ /**
 290+ * Updates the object in the database.
 291+ *
 292+ * @since 0.1
 293+ *
 294+ * @return boolean Success indicator
 295+ */
 296+ protected function updateInDB() {
 297+ $dbw = wfGetDB( DB_MASTER );
 298+
 299+ return $dbw->update(
 300+ $this->getDBTable(),
 301+ $this->getWriteValues(),
 302+ array( static::getFieldPrefix() . static::getIDField() => $this->getId() )
 303+ );
 304+ }
 305+
 306+ /**
 307+ * Inserts the object into the database.
 308+ *
 309+ * @since 0.1
 310+ *
 311+ * @return boolean Success indicator
 312+ */
 313+ protected function insertIntoDB() {
 314+ $dbw = wfGetDB( DB_MASTER );
 315+
 316+ $result = $dbw->insert(
 317+ static::getDBTable(),
 318+ static::getWriteValues()
 319+ );
 320+
 321+ $this->setField( static::getIDField(), $dbw->insertId() );
 322+
 323+ return $result;
 324+ }
 325+
 326+ /**
 327+ * Removes the object from the database.
 328+ *
 329+ * @since 0.1
 330+ *
 331+ * @return boolean Success indicator
 332+ */
 333+ public function removeFromDB() {
 334+ $dbw = wfGetDB( DB_MASTER );
 335+
 336+ $sucecss = $dbw->delete(
 337+ static::getDBTable(),
 338+ array( static::getFieldPrefix() . static::getIDField() => $this->getId() )
 339+ );
 340+
 341+ if ( $sucecss ) {
 342+ $this->setField( static::getIDField(), null );
 343+ }
 344+
 345+ return $sucecss;
 346+ }
 347+
 348+ /**
 349+ * Return the names of the fields.
 350+ *
 351+ * @since 0.1
 352+ *
 353+ * @return array
 354+ */
 355+ public function getFields() {
 356+ return $this->fields;
 357+ }
 358+
 359+ /**
 360+ * Return the names of the fields.
 361+ *
 362+ * @since 0.1
 363+ *
 364+ * @return array
 365+ */
 366+ public static function getFieldNames() {
 367+ return array_keys( static::getFieldTypes() );
 368+ }
 369+
 370+ /**
 371+ * Return the names of the fields.
 372+ *
 373+ * @since 0.1
 374+ *
 375+ * @return array
 376+ */
 377+ public function getSetFieldNames() {
 378+ return array_keys( $this->fields );
 379+ }
 380+
 381+ /**
 382+ * Sets the value of a field.
 383+ * Strings can be provided for other types,
 384+ * so this method can be called from unserialization handlers.
 385+ *
 386+ * @since 0.1
 387+ *
 388+ * @param string $name
 389+ * @param mixed $value
 390+ *
 391+ * @throws MWException
 392+ */
 393+ public function setField( $name, $value ) {
 394+ $fields = static::getFieldTypes();
 395+
 396+ if ( array_key_exists( $name, $fields ) ) {
 397+ switch ( $fields[$name] ) {
 398+ case 'int':
 399+ $value = (int)$value;
 400+ break;
 401+ case 'bool':
 402+ if ( is_string( $value ) ) {
 403+ $value = $value !== '0';
 404+ } elseif ( is_int( $value ) ) {
 405+ $value = $value !== 0;
 406+ }
 407+ break;
 408+ case 'array':
 409+ if ( is_string( $value ) ) {
 410+ $value = unserialize( $value );
 411+ }
 412+ break;
 413+ case 'id':
 414+ if ( is_string( $value ) ) {
 415+ $value = (int)$value;
 416+ }
 417+ break;
 418+ }
 419+
 420+ $this->fields[$name] = $value;
 421+ } else {
 422+ throw new MWException( 'Attempted to set unknonw field ' . $name );
 423+ }
 424+ }
 425+
 426+ /**
 427+ * Gets the value of a field.
 428+ *
 429+ * @since 0.1
 430+ *
 431+ * @param string $name
 432+ *
 433+ * @throws MWException
 434+ * @return mixed
 435+ */
 436+ public function getField( $name ) {
 437+ if ( $this->hasField( $name ) ) {
 438+ return $this->fields[$name];
 439+ } else {
 440+ throw new MWException( 'Attempted to get not-set field ' . $name );
 441+ }
 442+ }
 443+
 444+ /**
 445+ * Remove a field.
 446+ *
 447+ * @since 0.1
 448+ *
 449+ * @param string $name
 450+ */
 451+ public function removeField( $name ) {
 452+ unset( $this->fields[$name] );
 453+ }
 454+
 455+ /**
 456+ * Returns the objects database id.
 457+ *
 458+ * @since 0.1
 459+ *
 460+ * @return integer|null
 461+ */
 462+ public function getId() {
 463+ return $this->getField( static::getIDField() );
 464+ }
 465+
 466+ /**
 467+ * Sets the objects database id.
 468+ *
 469+ * @since 0.1
 470+ *
 471+ * @param integere|null $id
 472+ */
 473+ public function setId( $id ) {
 474+ return $this->setField( static::getIDField(), $id );
 475+ }
 476+
 477+ /**
 478+ * Gets if a certain field is set.
 479+ *
 480+ * @since 0.1
 481+ *
 482+ * @param string $name
 483+ *
 484+ * @return boolean
 485+ */
 486+ public function hasField( $name ) {
 487+ return array_key_exists( $name, $this->fields );
 488+ }
 489+
 490+ /**
 491+ * Gets if the object can take a certain field.
 492+ *
 493+ * @since 0.1
 494+ *
 495+ * @param string $name
 496+ *
 497+ * @return boolean
 498+ */
 499+ public static function canHasField( $name ) {
 500+ return array_key_exists( $name, static::getFieldTypes() );
 501+ }
 502+
 503+ /**
 504+ * Gets if the id field is set.
 505+ *
 506+ * @since 0.1
 507+ *
 508+ * @return boolean
 509+ */
 510+ public function hasIdField() {
 511+ return $this->hasField( static::getIDField() )
 512+ && !is_null( $this->getField( static::getIDField() ) );
 513+ }
 514+
 515+ /**
 516+ * Sets multiple fields.
 517+ *
 518+ * @since 0.1
 519+ *
 520+ * @param array $fields The fields to set
 521+ * @param boolean $override Override already set fields with the provided values?
 522+ */
 523+ public function setFields( array $fields, $override = true ) {
 524+ foreach ( $fields as $name => $value ) {
 525+ if ( $override || !$this->hasField( $name ) ) {
 526+ $this->setField( $name, $value );
 527+ }
 528+ }
 529+ }
 530+
 531+ /**
 532+ * Gets the fields => values to write to the table.
 533+ *
 534+ * @since 0.1
 535+ *
 536+ * @return array
 537+ */
 538+ protected function getWriteValues() {
 539+ $values = array();
 540+
 541+ foreach ( static::getFieldTypes() as $name => $type ) {
 542+ if ( array_key_exists( $name, $this->fields ) ) {
 543+ $value = $this->fields[$name];
 544+
 545+ switch ( $type ) {
 546+ case 'array':
 547+ $value = serialize( (array)$value );
 548+ }
 549+
 550+ $values[static::getFieldPrefix() . $name] = $value;
 551+ }
 552+ }
 553+
 554+ return $values;
 555+ }
 556+
 557+ /**
 558+ * Takes in a field or array of fields and returns an
 559+ * array with their prefixed versions, ready for db usage.
 560+ *
 561+ * @since 0.1
 562+ *
 563+ * @param array|string $fields
 564+ *
 565+ * @return array
 566+ */
 567+ public static function getPrefixedFields( $fields ) {
 568+ $fields = (array)$fields;
 569+
 570+ foreach ( $fields as &$field ) {
 571+ $field = static::getFieldPrefix() . $field;
 572+ }
 573+
 574+ return $fields;
 575+ }
 576+
 577+ /**
 578+ * Takes in a field and returns an it's prefixed version, ready for db usage.
 579+ *
 580+ * @since 0.1
 581+ *
 582+ * @param string $field
 583+ *
 584+ * @return string
 585+ */
 586+ public static function getPrefixedField( $field ) {
 587+ return static::getFieldPrefix() . $field;
 588+ }
 589+
 590+ /**
 591+ * Takes in an associative array with field names as keys and
 592+ * their values as value. The field names are prefixed with the
 593+ * db field prefix.
 594+ *
 595+ * @since 0.1
 596+ *
 597+ * @param array $values
 598+ *
 599+ * @return array
 600+ */
 601+ public static function getPrefixedValues( array $values ) {
 602+ $prefixedValues = array();
 603+
 604+ foreach ( $values as $field => $value ) {
 605+ $prefixedValues[static::getFieldPrefix() . $field] = $value;
 606+ }
 607+
 608+ return $prefixedValues;
 609+ }
 610+
 611+ /**
 612+ * Serializes the survey to an associative array which
 613+ * can then easily be converted into JSON or similar.
 614+ *
 615+ * @since 0.1
 616+ *
 617+ * @param null|array $props
 618+ *
 619+ * @return array
 620+ */
 621+ public function toArray( $fields = null ) {
 622+ $data = array();
 623+ $setFields = array();
 624+
 625+ if ( !is_array( $fields ) ) {
 626+ $setFields = $this->getSetFieldNames();
 627+ } else {
 628+ foreach ( $fields as $field ) {
 629+ if ( $this->hasField( $field ) ) {
 630+ $setFields[] = $field;
 631+ }
 632+ }
 633+ }
 634+
 635+ foreach ( $setFields as $field ) {
 636+ $data[$field] = $this->getField( $field );
 637+ }
 638+
 639+ return $data;
 640+ }
 641+
 642+ public function loadDefaults( $override = true ) {
 643+ $this->setFields( static::getDefaults(), $override );
 644+ }
 645+
 646+ /**
 647+ * Returns a list of default field values.
 648+ * field name => field value
 649+ *
 650+ * @since 0.1
 651+ *
 652+ * @return array
 653+ */
 654+ public static function getDefaults() {
 655+ return array();
 656+ }
 657+
 658+ /**
 659+ * Get API parameters for the fields supported by this object.
 660+ *
 661+ * @since 0.1
 662+ *
 663+ * @param boolean $requireParams
 664+ *
 665+ * @return array
 666+ */
 667+ public static function getAPIParams( $requireParams = true ) {
 668+ $typeMap = array(
 669+ 'id' => 'integer',
 670+ 'int' => 'integer',
 671+ 'str' => 'string',
 672+ 'bool' => 'integer',
 673+ 'array' => 'string'
 674+ );
 675+
 676+ $params = array();
 677+ $defaults = static::getDefaults();
 678+
 679+ foreach ( static::getFieldTypes() as $field => $type ) {
 680+ if ( $field == static::getIDField() ) {
 681+ continue;
 682+ }
 683+
 684+ $hasDefault = array_key_exists( $field, $defaults );
 685+
 686+ $params[$field] = array(
 687+ ApiBase::PARAM_TYPE => $typeMap[$type],
 688+ ApiBase::PARAM_REQUIRED => $requireParams && !$hasDefault
 689+ );
 690+
 691+ if ( $type == 'array' ) {
 692+ $params[$field][ApiBase::PARAM_ISMULTI] = true;
 693+ }
 694+
 695+ if ( $hasDefault ) {
 696+ $default = is_array( $defaults[$field] ) ? implode( '|', $defaults[$field] ) : $defaults[$field];
 697+ $params[$field][ApiBase::PARAM_DFLT] = $default;
 698+ }
 699+ }
 700+
 701+ return $params;
 702+ }
 703+
 704+ /**
 705+ * Takes an array of field name => field value and
 706+ * filters it on valid field names.
 707+ *
 708+ * @since 0.1
 709+ *
 710+ * @param array $conditions
 711+ * @param false|integer $id
 712+ *
 713+ * @return array
 714+ */
 715+ public static function getValidFields( array $conditions, $id = false ) {
 716+ $validFields = array();
 717+
 718+ $fields = static::getFieldTypes();
 719+
 720+ foreach ( $conditions as $name => $value ) {
 721+ if ( array_key_exists( $name, $fields ) ) {
 722+ $validFields[$name] = $value;
 723+ }
 724+ }
 725+
 726+ if ( $id !== false ) {
 727+ $validParams[static::getIDField()] = $id;
 728+ }
 729+
 730+ return $validFields;
 731+ }
 732+
 733+}
Property changes on: tags/extensions/Survey/REL_0_1_2/includes/SurveyDBClass.php
___________________________________________________________________
Added: svn:eol-style
1734 + native
Index: tags/extensions/Survey/REL_0_1_2/includes/SurveySubmission.php
@@ -0,0 +1,110 @@
 2+<?php
 3+
 4+/**
 5+ * Simple survey submission object class.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SurveySubmission.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SurveySubmission extends SurveyDBClass {
 16+
 17+ /**
 18+ * @see SurveyDBClass::getDBTable()
 19+ */
 20+ public static function getDBTable() {
 21+ return 'survey_submissions';
 22+ }
 23+
 24+ /**
 25+ * Gets the db field prefix.
 26+ *
 27+ * @since 0.1
 28+ *
 29+ * @return string
 30+ */
 31+ protected static function getFieldPrefix() {
 32+ return 'submission_';
 33+ }
 34+
 35+ /**
 36+ * Returns an array with the fields and their types this object contains.
 37+ * This corresponds directly to the fields in the database, without prefix.
 38+ *
 39+ * survey_id:
 40+ * The ID of the survey this submission is for.
 41+ *
 42+ * page_id:
 43+ * The ID of the page this submission was made on.
 44+ *
 45+ * user_name:
 46+ * The name of the user that made the submission (username or ip).
 47+ *
 48+ * time:
 49+ * Timestamp idnicating when the submission was made.
 50+ *
 51+ * @since 0.1
 52+ *
 53+ * @return array
 54+ */
 55+ protected static function getFieldTypes() {
 56+ return array(
 57+ 'id' => 'id',
 58+ 'survey_id' => 'id',
 59+ 'page_id' => 'id',
 60+ 'user_name' => 'str',
 61+ 'time' => 'str',
 62+ );
 63+ }
 64+
 65+ /**
 66+ * List of answers.
 67+ *
 68+ * @since 0.1
 69+ * @var array of SurveyAnswer
 70+ */
 71+ protected $answers;
 72+
 73+
 74+ public function addAnswer( SurveyAnswer $answer ) {
 75+ $this->answers[] = $answer;
 76+ }
 77+
 78+ public function setAnswers( array $answers ) {
 79+ $this->answers = $answers;
 80+ }
 81+
 82+ public function getAnswers() {
 83+ return $this->answers;
 84+ }
 85+
 86+ /**
 87+ * Writes the answer to the database, either updating it
 88+ * when it already exists, or inserting it when it doesn't.
 89+ *
 90+ * @since 0.1
 91+ *
 92+ * @return boolean Success indicator
 93+ */
 94+ public function writeToDB() {
 95+ $success = parent::writeToDB();
 96+
 97+ if ( $success ) {
 98+ $this->writeAnswersToDB();
 99+ }
 100+
 101+ return $success;
 102+ }
 103+
 104+ public function writeAnswersToDB() {
 105+ foreach ( $this->answers as /* SurveyAnswer */ $answer ) {
 106+ $answer->setField( 'submission_id', $this->getId() );
 107+ $answer->writeToDB();
 108+ }
 109+ }
 110+
 111+}
Property changes on: tags/extensions/Survey/REL_0_1_2/includes/SurveySubmission.php
___________________________________________________________________
Added: svn:eol-style
1112 + native
Index: tags/extensions/Survey/REL_0_1_2/includes/SurveyTag.php
@@ -0,0 +1,108 @@
 2+<?php
 3+
 4+/**
 5+ * Class to render survey tags.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SurveyTag.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3+
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SurveyTag {
 16+
 17+ /**
 18+ * List of survey parameters.
 19+ *
 20+ * @since 0.1
 21+ *
 22+ * @var array
 23+ */
 24+ protected $parameters;
 25+
 26+ protected $contents;
 27+
 28+ /**
 29+ * Constructor.
 30+ *
 31+ * @since 0.1
 32+ *
 33+ * @param array $args
 34+ * @param string|null $contents
 35+ */
 36+ public function __construct( array $args, $contents = null ) {
 37+ $this->parameters = $args;
 38+ $this->contents = $contents;
 39+
 40+ $args = filter_var_array( $args, $this->getSurveyParameters() );
 41+
 42+ if ( is_array( $args ) ) {
 43+ $this->parameters = array();
 44+
 45+ foreach ( $args as $name => $value ) {
 46+ if ( !is_null( $value ) && $value !== false ) {
 47+ $this->parameters['survey-data-' . $name] = $value;
 48+ }
 49+ }
 50+
 51+ $this->parameters['class'] = 'surveytag';
 52+ $this->parameters['survey-data-token'] =
 53+ $GLOBALS['wgUser']->editToken( serialize( array( 'submitsurvey', $GLOBALS['wgUser']->getName() ) ) );
 54+ } else {
 55+ throw new MWException( 'Invalid parameters for survey tag.' );
 56+ }
 57+ }
 58+
 59+ /**
 60+ * Renrder the survey div.
 61+ *
 62+ * @since 0.1
 63+ *
 64+ * @param Parser $parser
 65+ *
 66+ * @return string
 67+ */
 68+ public function render( Parser $parser ) {
 69+ static $loadedJs = false;
 70+
 71+ if ( !$loadedJs ) {
 72+ $parser->getOutput()->addModules( 'ext.survey.tag' );
 73+ $parser->getOutput()->addHeadItem(
 74+ Skin::makeVariablesScript( array(
 75+ 'wgSurveyDebug' => SurveySettings::get( 'JSDebug' )
 76+ ) )
 77+ );
 78+ }
 79+
 80+ return Html::element(
 81+ 'span',
 82+ $this->parameters,
 83+ $this->contents
 84+ );
 85+ }
 86+
 87+ /**
 88+ *
 89+ *
 90+ * @since 0.1
 91+ *
 92+ * @param array $args
 93+ *
 94+ * @return array
 95+ */
 96+ protected function getSurveyParameters() {
 97+ return array(
 98+ 'id' => array( 'filter' => FILTER_VALIDATE_INT, 'options' => array( 'min_range' => 1 ) ),
 99+ 'name' => array(),
 100+ 'cookie' => array(),
 101+ 'title' => array(),
 102+ 'require-enabled' => array( 'filter' => FILTER_VALIDATE_INT, 'options' => array( 'min_range' => 0, 'max_range' => 1 ) ),
 103+ 'expiry' => array( 'filter' => FILTER_VALIDATE_INT, 'options' => array( 'min_range' => 0 ) ),
 104+ 'min-pages' => array( 'filter' => FILTER_VALIDATE_INT, 'options' => array( 'min_range' => 0 ) ),
 105+ 'ratio' => array( 'filter' => FILTER_VALIDATE_INT, 'options' => array( 'min_range' => 0, 'max_range' => 100 ) ),
 106+ );
 107+ }
 108+
 109+}
Property changes on: tags/extensions/Survey/REL_0_1_2/includes/SurveyTag.php
___________________________________________________________________
Added: svn:eol-style
1110 + native
Index: tags/extensions/Survey/REL_0_1_2/includes/SurveyAnswer.php
@@ -0,0 +1,60 @@
 2+<?php
 3+
 4+/**
 5+ * Simple survey submission object class.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SurveySubmission.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SurveyAnswer extends SurveyDBClass {
 16+
 17+ /**
 18+ * @see SurveyDBClass::getDBTable()
 19+ */
 20+ public static function getDBTable() {
 21+ return 'survey_answers';
 22+ }
 23+
 24+ /**
 25+ * Gets the db field prefix.
 26+ *
 27+ * @since 0.1
 28+ *
 29+ * @return string
 30+ */
 31+ protected static function getFieldPrefix() {
 32+ return 'answer_';
 33+ }
 34+
 35+ /**
 36+ * Returns an array with the fields and their types this object contains.
 37+ * This corresponds directly to the fields in the database, without prefix.
 38+ *
 39+ * text:
 40+ * The answer text.
 41+ *
 42+ * submission_id:
 43+ * The ID of the submission this answer is part of.
 44+ *
 45+ * question_id:
 46+ * The ID of the question this answer corresponds to.
 47+ *
 48+ * @since 0.1
 49+ *
 50+ * @return array
 51+ */
 52+ protected static function getFieldTypes() {
 53+ return array(
 54+ 'id' => 'id',
 55+ 'text' => 'str',
 56+ 'submission_id' => 'id',
 57+ 'question_id' => 'id',
 58+ );
 59+ }
 60+
 61+}
Property changes on: tags/extensions/Survey/REL_0_1_2/includes/SurveyAnswer.php
___________________________________________________________________
Added: svn:eol-style
162 + native
Index: tags/extensions/Survey/REL_0_1_2/includes/Survey.class.php
@@ -0,0 +1,338 @@
 2+<?php
 3+
 4+/**
 5+ * Simple Survey object class.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file Survey.class.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class Survey extends SurveyDBClass {
 16+
 17+ public static $USER_ALL = 0;
 18+ public static $USER_LOGGEDIN = 1;
 19+ public static $USER_CONFIRMED = 2;
 20+ public static $USER_EDITOR = 3;
 21+ public static $USER_ANON = 4;
 22+
 23+ /**
 24+ * @see SurveyDBClass::getDBTable()
 25+ */
 26+ public static function getDBTable() {
 27+ return 'surveys';
 28+ }
 29+
 30+ /**
 31+ * Returns an array with the fields and their types this object contains.
 32+ * This corresponds directly to the fields in the database, without prefix.
 33+ *
 34+ * @since 0.1
 35+ *
 36+ * @return array
 37+ */
 38+ protected static function getFieldTypes() {
 39+ return array(
 40+ 'id' => 'id',
 41+ 'name' => 'str',
 42+ 'title' => 'str',
 43+ 'enabled' => 'bool',
 44+ 'header' => 'str',
 45+ 'footer' => 'str',
 46+ 'thanks' => 'str',
 47+ 'user_type' => 'int',
 48+ 'namespaces' => 'array',
 49+ 'ratio' => 'int',
 50+ 'expiry' => 'int',
 51+ 'min_pages' => 'int'
 52+ );
 53+ }
 54+
 55+ /**
 56+ * Returns a list of default field values.
 57+ * field name => field value
 58+ *
 59+ * @since 0.1
 60+ *
 61+ * @return array
 62+ */
 63+ public static function getDefaults() {
 64+ return array(
 65+ 'name' => '',
 66+ 'title' => '',
 67+ 'enabled' => SurveySettings::get( 'defaultEnabled' ) ? '1' : '0',
 68+ 'header' => 'Thank you for taking this short survey. Please fill out the following questions:',
 69+ 'footer' => '',
 70+ 'thanks' => 'Thank you for your responses.',
 71+ 'user_type' => SurveySettings::get( 'defaultUserType' ),
 72+ 'namespaces' => SurveySettings::get( 'defaultNamespaces' ),
 73+ 'ratio' => SurveySettings::get( 'defaultRatio' ),
 74+ 'expiry' => SurveySettings::get( 'defaultExpiry' ),
 75+ 'min_pages' => SurveySettings::get( 'defaultMinPages' ),
 76+ );
 77+ }
 78+
 79+ /**
 80+ * Gets the db field prefix.
 81+ *
 82+ * @since 0.1
 83+ *
 84+ * @return string
 85+ */
 86+ protected static function getFieldPrefix() {
 87+ return 'survey_';
 88+ }
 89+
 90+ /**
 91+ * Returns the Survey with specified name, or false if there is no such survey.
 92+ *
 93+ * @since 0.1
 94+ *
 95+ * @param string $surveyName
 96+ * @param array|null $fields
 97+ * @param boolean $loadQuestions
 98+ *
 99+ * @return Survey or false
 100+ */
 101+ public static function newFromName( $surveyName, $fields = null, $loadQuestions = true ) {
 102+ return self::newFromDB( array( 'name' => $surveyName ), $fields, $loadQuestions );
 103+ }
 104+
 105+ /**
 106+ * Returns the Survey with specified ID, or false if there is no such survey.
 107+ *
 108+ * @since 0.1
 109+ *
 110+ * @param integer surveyId
 111+ * @param array|null $fields
 112+ * @param boolean $loadQuestions
 113+ *
 114+ * @return Survey or false
 115+ */
 116+ public static function newFromId( $surveyId, $fields = null, $loadQuestions = true ) {
 117+ return self::newFromDB( array( 'id' => $surveyId ), $fields, $loadQuestions );
 118+ }
 119+
 120+ /**
 121+ * Returns a new instance of Survey build from a database result
 122+ * obtained by doing a select with the porvided conditions on the surveys table.
 123+ * If no survey matches the conditions, false will be returned.
 124+ *
 125+ * @since 0.1
 126+ *
 127+ * @param array $conditions
 128+ * @param array|null $fields
 129+ * @param boolean $loadQuestions
 130+ *
 131+ * @return Survey or false
 132+ */
 133+ public static function newFromDB( array $conditions, $fields = null, $loadQuestions = true ) {
 134+ $survey = self::selectRow( $fields, $conditions );
 135+
 136+ if ( $survey !== false && $loadQuestions ) {
 137+ $survey->loadQuestionsFromDB();
 138+ }
 139+
 140+ return $survey;
 141+ }
 142+
 143+ /**
 144+ * The questions that go with this survey.
 145+ *
 146+ * @since 0.1
 147+ * @var array of SurveyQuestion
 148+ */
 149+ protected $questions;
 150+
 151+ /**
 152+ * Constructor.
 153+ *
 154+ * @since 0.1
 155+ *
 156+ * @param array|null $fields
 157+ * @param boolean $loadDefaults
 158+ * @param array $questions
 159+ */
 160+ public function __construct( $fields, $loadDefaults = false, array $questions = array() ) {
 161+ parent::__construct( $fields, $loadDefaults );
 162+ $this->setQuestions( $questions );
 163+ }
 164+
 165+ /**
 166+ * Load the surveys questions from the database.
 167+ *
 168+ * @since 0.1
 169+ */
 170+ public function loadQuestionsFromDB() {
 171+ $this->questions = SurveyQuestion::getQuestionsForSurvey( $this->getId() );
 172+ }
 173+
 174+ /**
 175+ * Writes the surveyand it's questions to the database, either updating it
 176+ * when it already exists, or inserting it when it doesn't.
 177+ *
 178+ * @since 0.1
 179+ *
 180+ * @return boolean Success indicator
 181+ */
 182+ public function writeToDB() {
 183+ $success = parent::writeToDB();
 184+
 185+ if ( $success ) {
 186+ $success = $this->writeQuestionsToDB();
 187+ }
 188+
 189+ return $success;
 190+ }
 191+
 192+ /**
 193+ * Writes the surveys questions to the database.
 194+ *
 195+ * @since 0.1
 196+ *
 197+ * @return boolean Success indicator
 198+ */
 199+ public function writeQuestionsToDB() {
 200+ $success = true;
 201+
 202+ $dbw = wfGetDB( DB_MASTER );
 203+
 204+ $dbw->begin();
 205+
 206+ SurveyQuestion::update(
 207+ array( 'removed' => 1 ),
 208+ array( 'survey_id' => $this->getId() )
 209+ );
 210+
 211+ foreach ( $this->questions as /* SurveyQuestion */ $question ) {
 212+ $question->setField( 'survey_id', $this->getId() );
 213+ $success = $question->writeToDB() && $success;
 214+ }
 215+
 216+ $dbw->commit();
 217+
 218+ return $success;
 219+ }
 220+
 221+ /**
 222+ * Returns the surveys questions.
 223+ *
 224+ * @since 0.1
 225+ *
 226+ * @return array of SurveyQuestion
 227+ */
 228+ public function getQuestions() {
 229+ return $this->questions;
 230+ }
 231+
 232+ /**
 233+ * Sets the surveys questions.
 234+ *
 235+ * @since 0.1
 236+ *
 237+ * @param array $questions list of SurveyQuestion
 238+ */
 239+ public function setQuestions( array /* of SurveyQuestion */ $questions ) {
 240+ $this->questions = $questions;
 241+ }
 242+
 243+ /**
 244+ * Serializes the survey to an associative array which
 245+ * can then easily be converted into JSON or similar.
 246+ *
 247+ * @since 0.1
 248+ *
 249+ * @param null|array $fields
 250+ *
 251+ * @return array
 252+ */
 253+ public function toArray( $fields = null ) {
 254+ $data = parent::toArray( $fields );
 255+
 256+ $data['questions'] = array();
 257+
 258+ foreach ( $this->questions as /* SurveyQuestion */ $question ) {
 259+ $data['questions'][] = $question->toArray();
 260+ }
 261+
 262+ return $data;
 263+ }
 264+
 265+ /**
 266+ * Removes the object from the database.
 267+ *
 268+ * @since 0.1
 269+ *
 270+ * @return boolean Success indicator
 271+ */
 272+ public function removeFromDB() {
 273+ $dbr= wfgetDB( DB_SLAVE );
 274+
 275+ $submissionsForSurvey = $dbr->select(
 276+ 'survey_submissions',
 277+ array( 'submission_id' ),
 278+ array( 'submission_survey_id' => $this->getId() )
 279+ );
 280+
 281+ $dbw = wfGetDB( DB_MASTER );
 282+
 283+ $dbw->begin();
 284+
 285+ $sucecss = parent::removeFromDB();
 286+
 287+ $sucecss = $dbw->delete(
 288+ 'survey_questions',
 289+ array( 'question_survey_id' => $this->getId() )
 290+ ) && $sucecss;
 291+
 292+ $sucecss = $dbw->delete(
 293+ 'survey_submissions',
 294+ array( 'submission_survey_id' => $this->getId() )
 295+ ) && $sucecss;
 296+
 297+ foreach ( $submissionsForSurvey as $nr => $submission ) {
 298+ $sucecss = $dbw->delete(
 299+ 'survey_answers',
 300+ array( 'answer_submission_id' => $submission->id )
 301+ ) && $sucecss;
 302+
 303+ if ( $nr % 500 == 0 ) {
 304+ $dbw->commit();
 305+ $dbw->begin();
 306+ }
 307+ }
 308+
 309+ $dbw->commit();
 310+
 311+ return $sucecss;
 312+ }
 313+
 314+ /**
 315+ * Returns the survey user types the provided user has.
 316+ *
 317+ * @since 0.1
 318+ *
 319+ * @param User $user
 320+ *
 321+ * @return array of Survey::$USER_
 322+ */
 323+ public static function getTypesForUser( User $user ) {
 324+ $userTypes = array( Survey::$USER_ALL );
 325+
 326+ $userTypes[] = $user->isLoggedIn() ? Survey::$USER_LOGGEDIN : Survey::$USER_ANON;
 327+
 328+ if ( $user->isEmailConfirmed() ) {
 329+ $userTypes[] = Survey::$USER_CONFIRMED;
 330+ }
 331+
 332+ if ( $user->getEditCount() > 0 ) {
 333+ $userTypes[] = Survey::$USER_EDITOR;
 334+ }
 335+
 336+ return $userTypes;
 337+ }
 338+
 339+}
Property changes on: tags/extensions/Survey/REL_0_1_2/includes/Survey.class.php
___________________________________________________________________
Added: svn:eol-style
1340 + native
Index: tags/extensions/Survey/REL_0_1_2/includes/SurveyCompat.php
@@ -0,0 +1,20 @@
 2+<?php
 3+
 4+/**
 5+ * Compatibility methods needed for Survey to work with older
 6+ * versions of MediaWiki.
 7+ *
 8+ * @since 0.1
 9+ *
 10+ * @file SurveyCompat.php
 11+ * @ingroup Survey
 12+ *
 13+ * @licence GNU GPL v3 or later
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+
 17+class SurveyCompat {
 18+
 19+
 20+
 21+}
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/includes/SurveyCompat.php
___________________________________________________________________
Added: svn:eol-style
122 + native
Index: tags/extensions/Survey/REL_0_1_2/includes/SurveyQuestion.php
@@ -0,0 +1,189 @@
 2+<?php
 3+
 4+/**
 5+ * Simple survey question object class.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file SurveyQuestion.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class SurveyQuestion extends SurveyDBClass {
 16+
 17+ public static $TYPE_TEXT = 0;
 18+ public static $TYPE_NUMBER = 1;
 19+ public static $TYPE_SELECT = 2;
 20+ public static $TYPE_RADIO = 3;
 21+ public static $TYPE_TEXTAREA = 4;
 22+ public static $TYPE_CHECK = 5;
 23+
 24+ /**
 25+ * @see SurveyDBClass::getDBTable()
 26+ */
 27+ public static function getDBTable() {
 28+ return 'survey_questions';
 29+ }
 30+
 31+ /**
 32+ * Gets the db field prefix.
 33+ *
 34+ * @since 0.1
 35+ *
 36+ * @return string
 37+ */
 38+ protected static function getFieldPrefix() {
 39+ return 'question_';
 40+ }
 41+
 42+ /**
 43+ * Returns an array with the fields and their types this object contains.
 44+ * This corresponds directly to the fields in the database, without prefix.
 45+ *
 46+ * survey_id:
 47+ * The ID of the survey this question belongs to.
 48+ * This can be null. When written to the db via Survey::writeToDB of
 49+ * a Survey holding this question, the survey ID will first be set.
 50+ *
 51+ * text:
 52+ * The question text.
 53+ *
 54+ * type:
 55+ * The question type.
 56+ *
 57+ * required:
 58+ * Indicated if the question is required,
 59+ * ie if the user can not submit the survey without answering it.
 60+ *
 61+ * answers:
 62+ * List of allowed values for the question.
 63+ * Empty list for no restrictions.
 64+ *
 65+ * removed:
 66+ * Indicated if the question was removed.
 67+ * Removed questions are kept in the db so their answers can
 68+ * still be used untill the survey itself gets removed.
 69+ *
 70+ * @since 0.1
 71+ *
 72+ * @return array
 73+ */
 74+ protected static function getFieldTypes() {
 75+ return array(
 76+ 'id' => 'id',
 77+ 'survey_id' => 'int',
 78+ 'text' => 'str',
 79+ 'type' => 'int',
 80+ 'required' => 'bool',
 81+ 'answers' => 'array',
 82+ 'removed' => 'bool',
 83+ );
 84+ }
 85+
 86+ /**
 87+ * Returns a list of default field values.
 88+ * field name => field value
 89+ *
 90+ * @since 0.1
 91+ *
 92+ * @return array
 93+ */
 94+ public static function getDefaults() {
 95+ return array(
 96+ 'text' => '',
 97+ 'type' => self::$TYPE_TEXT,
 98+ 'required' => false,
 99+ 'answers' => array(),
 100+ 'removed' => false,
 101+ );
 102+ }
 103+
 104+ /**
 105+ * Unserialization method for survey question data passed as a multi-value API parameter.
 106+ * Uses base64 and replaces padding = by !, so the values does not contain any = or |.
 107+ *
 108+ * @since 0.1
 109+ *
 110+ * @param string $args
 111+ *
 112+ * @return SurveyQuestion
 113+ */
 114+ public static function newFromUrlData( $args ) {
 115+ $args = (array)FormatJson::decode( base64_decode( str_replace( '!', '=', $args ) ) );
 116+ return self::newFromArray( $args );
 117+ }
 118+
 119+ /**
 120+ * Serialization method for survey questions that need to be passed via multi-value API parameter.
 121+ * Uses base64 and replaces padding = by !, so the values does not contain any = or |.
 122+ *
 123+ * @since 0.1
 124+ *
 125+ * @return string
 126+ */
 127+ public function toUrlData() {
 128+ return str_replace( '=', '!', base64_encode( FormatJson::encode( $this->toArray() ) ) );
 129+ }
 130+
 131+ /**
 132+ * Returns the questions for the specified survey.
 133+ *
 134+ * @since 0.1
 135+ *
 136+ * @param integer $surveyId
 137+ * @param boolean $incRemoved
 138+ *
 139+ * @return array of SurveyQuestion
 140+ */
 141+ public static function getQuestionsForSurvey( $surveyId, $incRemoved = false ) {
 142+ $conditions = array( 'survey_id' => $surveyId );
 143+
 144+ if ( $incRemoved === false ) {
 145+ $conditions['removed'] = 0;
 146+ }
 147+
 148+ return self::select( null, $conditions );
 149+ }
 150+
 151+ /**
 152+ * Gets the message for a question type.
 153+ * The message key, not the internationalized string.
 154+ *
 155+ * @since 0.1
 156+ *
 157+ * @param integer $type
 158+ *
 159+ * @return string
 160+ */
 161+ public static function getTypeMessage( $type ) {
 162+ static $messageMap = false;
 163+
 164+ if ( $messageMap === false ) {
 165+ $messageMap = array(
 166+ self::$TYPE_TEXT => 'text',
 167+ self::$TYPE_NUMBER => 'number',
 168+ self::$TYPE_SELECT => 'select',
 169+ self::$TYPE_RADIO => 'radio',
 170+ self::$TYPE_TEXTAREA => 'textarea',
 171+ self::$TYPE_CHECK => 'check',
 172+ );
 173+ }
 174+
 175+ return 'survey-question-type-' . $messageMap[$type];
 176+ }
 177+
 178+ /**
 179+ * Returns if the type of the question is restrictive,
 180+ * ie if the question input only allows certain answers.
 181+ *
 182+ * @since 0.1
 183+ *
 184+ * @return boolean
 185+ */
 186+ public function isRestrictiveType() {
 187+ return in_array( $this->getField( 'type' ), array( self::$TYPE_SELECT, self::$TYPE_RADIO, self::$TYPE_CHECK ) );
 188+ }
 189+
 190+}
Property changes on: tags/extensions/Survey/REL_0_1_2/includes/SurveyQuestion.php
___________________________________________________________________
Added: svn:eol-style
1191 + native
Index: tags/extensions/Survey/REL_0_1_2/COPYING
@@ -0,0 +1,682 @@
 2+The license text below "----" applies to all files within this distribution, other
 3+than those that are in a directory which contains files named "LICENSE" or
 4+"COPYING", or a subdirectory thereof. For those files, the license text contained in
 5+said file overrides any license information contained in directories of smaller depth.
 6+Alternative licenses are typically used for software that is provided by external
 7+parties, and merely packaged with this software for convenience.
 8+----
 9+
 10+ GNU GENERAL PUBLIC LICENSE
 11+ Version 3, 29 June 2007
 12+
 13+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 14+ Everyone is permitted to copy and distribute verbatim copies
 15+ of this license document, but changing it is not allowed.
 16+
 17+ Preamble
 18+
 19+ The GNU General Public License is a free, copyleft license for
 20+software and other kinds of works.
 21+
 22+ The licenses for most software and other practical works are designed
 23+to take away your freedom to share and change the works. By contrast,
 24+the GNU General Public License is intended to guarantee your freedom to
 25+share and change all versions of a program--to make sure it remains free
 26+software for all its users. We, the Free Software Foundation, use the
 27+GNU General Public License for most of our software; it applies also to
 28+any other work released this way by its authors. You can apply it to
 29+your programs, too.
 30+
 31+ When we speak of free software, we are referring to freedom, not
 32+price. Our General Public Licenses are designed to make sure that you
 33+have the freedom to distribute copies of free software (and charge for
 34+them if you wish), that you receive source code or can get it if you
 35+want it, that you can change the software or use pieces of it in new
 36+free programs, and that you know you can do these things.
 37+
 38+ To protect your rights, we need to prevent others from denying you
 39+these rights or asking you to surrender the rights. Therefore, you have
 40+certain responsibilities if you distribute copies of the software, or if
 41+you modify it: responsibilities to respect the freedom of others.
 42+
 43+ For example, if you distribute copies of such a program, whether
 44+gratis or for a fee, you must pass on to the recipients the same
 45+freedoms that you received. You must make sure that they, too, receive
 46+or can get the source code. And you must show them these terms so they
 47+know their rights.
 48+
 49+ Developers that use the GNU GPL protect your rights with two steps:
 50+(1) assert copyright on the software, and (2) offer you this License
 51+giving you legal permission to copy, distribute and/or modify it.
 52+
 53+ For the developers' and authors' protection, the GPL clearly explains
 54+that there is no warranty for this free software. For both users' and
 55+authors' sake, the GPL requires that modified versions be marked as
 56+changed, so that their problems will not be attributed erroneously to
 57+authors of previous versions.
 58+
 59+ Some devices are designed to deny users access to install or run
 60+modified versions of the software inside them, although the manufacturer
 61+can do so. This is fundamentally incompatible with the aim of
 62+protecting users' freedom to change the software. The systematic
 63+pattern of such abuse occurs in the area of products for individuals to
 64+use, which is precisely where it is most unacceptable. Therefore, we
 65+have designed this version of the GPL to prohibit the practice for those
 66+products. If such problems arise substantially in other domains, we
 67+stand ready to extend this provision to those domains in future versions
 68+of the GPL, as needed to protect the freedom of users.
 69+
 70+ Finally, every program is threatened constantly by software patents.
 71+States should not allow patents to restrict development and use of
 72+software on general-purpose computers, but in those that do, we wish to
 73+avoid the special danger that patents applied to a free program could
 74+make it effectively proprietary. To prevent this, the GPL assures that
 75+patents cannot be used to render the program non-free.
 76+
 77+ The precise terms and conditions for copying, distribution and
 78+modification follow.
 79+
 80+ TERMS AND CONDITIONS
 81+
 82+ 0. Definitions.
 83+
 84+ "This License" refers to version 3 of the GNU General Public License.
 85+
 86+ "Copyright" also means copyright-like laws that apply to other kinds of
 87+works, such as semiconductor masks.
 88+
 89+ "The Program" refers to any copyrightable work licensed under this
 90+License. Each licensee is addressed as "you". "Licensees" and
 91+"recipients" may be individuals or organizations.
 92+
 93+ To "modify" a work means to copy from or adapt all or part of the work
 94+in a fashion requiring copyright permission, other than the making of an
 95+exact copy. The resulting work is called a "modified version" of the
 96+earlier work or a work "based on" the earlier work.
 97+
 98+ A "covered work" means either the unmodified Program or a work based
 99+on the Program.
 100+
 101+ To "propagate" a work means to do anything with it that, without
 102+permission, would make you directly or secondarily liable for
 103+infringement under applicable copyright law, except executing it on a
 104+computer or modifying a private copy. Propagation includes copying,
 105+distribution (with or without modification), making available to the
 106+public, and in some countries other activities as well.
 107+
 108+ To "convey" a work means any kind of propagation that enables other
 109+parties to make or receive copies. Mere interaction with a user through
 110+a computer network, with no transfer of a copy, is not conveying.
 111+
 112+ An interactive user interface displays "Appropriate Legal Notices"
 113+to the extent that it includes a convenient and prominently visible
 114+feature that (1) displays an appropriate copyright notice, and (2)
 115+tells the user that there is no warranty for the work (except to the
 116+extent that warranties are provided), that licensees may convey the
 117+work under this License, and how to view a copy of this License. If
 118+the interface presents a list of user commands or options, such as a
 119+menu, a prominent item in the list meets this criterion.
 120+
 121+ 1. Source Code.
 122+
 123+ The "source code" for a work means the preferred form of the work
 124+for making modifications to it. "Object code" means any non-source
 125+form of a work.
 126+
 127+ A "Standard Interface" means an interface that either is an official
 128+standard defined by a recognized standards body, or, in the case of
 129+interfaces specified for a particular programming language, one that
 130+is widely used among developers working in that language.
 131+
 132+ The "System Libraries" of an executable work include anything, other
 133+than the work as a whole, that (a) is included in the normal form of
 134+packaging a Major Component, but which is not part of that Major
 135+Component, and (b) serves only to enable use of the work with that
 136+Major Component, or to implement a Standard Interface for which an
 137+implementation is available to the public in source code form. A
 138+"Major Component", in this context, means a major essential component
 139+(kernel, window system, and so on) of the specific operating system
 140+(if any) on which the executable work runs, or a compiler used to
 141+produce the work, or an object code interpreter used to run it.
 142+
 143+ The "Corresponding Source" for a work in object code form means all
 144+the source code needed to generate, install, and (for an executable
 145+work) run the object code and to modify the work, including scripts to
 146+control those activities. However, it does not include the work's
 147+System Libraries, or general-purpose tools or generally available free
 148+programs which are used unmodified in performing those activities but
 149+which are not part of the work. For example, Corresponding Source
 150+includes interface definition files associated with source files for
 151+the work, and the source code for shared libraries and dynamically
 152+linked subprograms that the work is specifically designed to require,
 153+such as by intimate data communication or control flow between those
 154+subprograms and other parts of the work.
 155+
 156+ The Corresponding Source need not include anything that users
 157+can regenerate automatically from other parts of the Corresponding
 158+Source.
 159+
 160+ The Corresponding Source for a work in source code form is that
 161+same work.
 162+
 163+ 2. Basic Permissions.
 164+
 165+ All rights granted under this License are granted for the term of
 166+copyright on the Program, and are irrevocable provided the stated
 167+conditions are met. This License explicitly affirms your unlimited
 168+permission to run the unmodified Program. The output from running a
 169+covered work is covered by this License only if the output, given its
 170+content, constitutes a covered work. This License acknowledges your
 171+rights of fair use or other equivalent, as provided by copyright law.
 172+
 173+ You may make, run and propagate covered works that you do not
 174+convey, without conditions so long as your license otherwise remains
 175+in force. You may convey covered works to others for the sole purpose
 176+of having them make modifications exclusively for you, or provide you
 177+with facilities for running those works, provided that you comply with
 178+the terms of this License in conveying all material for which you do
 179+not control copyright. Those thus making or running the covered works
 180+for you must do so exclusively on your behalf, under your direction
 181+and control, on terms that prohibit them from making any copies of
 182+your copyrighted material outside their relationship with you.
 183+
 184+ Conveying under any other circumstances is permitted solely under
 185+the conditions stated below. Sublicensing is not allowed; section 10
 186+makes it unnecessary.
 187+
 188+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 189+
 190+ No covered work shall be deemed part of an effective technological
 191+measure under any applicable law fulfilling obligations under article
 192+11 of the WIPO copyright treaty adopted on 20 December 1996, or
 193+similar laws prohibiting or restricting circumvention of such
 194+measures.
 195+
 196+ When you convey a covered work, you waive any legal power to forbid
 197+circumvention of technological measures to the extent such circumvention
 198+is effected by exercising rights under this License with respect to
 199+the covered work, and you disclaim any intention to limit operation or
 200+modification of the work as a means of enforcing, against the work's
 201+users, your or third parties' legal rights to forbid circumvention of
 202+technological measures.
 203+
 204+ 4. Conveying Verbatim Copies.
 205+
 206+ You may convey verbatim copies of the Program's source code as you
 207+receive it, in any medium, provided that you conspicuously and
 208+appropriately publish on each copy an appropriate copyright notice;
 209+keep intact all notices stating that this License and any
 210+non-permissive terms added in accord with section 7 apply to the code;
 211+keep intact all notices of the absence of any warranty; and give all
 212+recipients a copy of this License along with the Program.
 213+
 214+ You may charge any price or no price for each copy that you convey,
 215+and you may offer support or warranty protection for a fee.
 216+
 217+ 5. Conveying Modified Source Versions.
 218+
 219+ You may convey a work based on the Program, or the modifications to
 220+produce it from the Program, in the form of source code under the
 221+terms of section 4, provided that you also meet all of these conditions:
 222+
 223+ a) The work must carry prominent notices stating that you modified
 224+ it, and giving a relevant date.
 225+
 226+ b) The work must carry prominent notices stating that it is
 227+ released under this License and any conditions added under section
 228+ 7. This requirement modifies the requirement in section 4 to
 229+ "keep intact all notices".
 230+
 231+ c) You must license the entire work, as a whole, under this
 232+ License to anyone who comes into possession of a copy. This
 233+ License will therefore apply, along with any applicable section 7
 234+ additional terms, to the whole of the work, and all its parts,
 235+ regardless of how they are packaged. This License gives no
 236+ permission to license the work in any other way, but it does not
 237+ invalidate such permission if you have separately received it.
 238+
 239+ d) If the work has interactive user interfaces, each must display
 240+ Appropriate Legal Notices; however, if the Program has interactive
 241+ interfaces that do not display Appropriate Legal Notices, your
 242+ work need not make them do so.
 243+
 244+ A compilation of a covered work with other separate and independent
 245+works, which are not by their nature extensions of the covered work,
 246+and which are not combined with it such as to form a larger program,
 247+in or on a volume of a storage or distribution medium, is called an
 248+"aggregate" if the compilation and its resulting copyright are not
 249+used to limit the access or legal rights of the compilation's users
 250+beyond what the individual works permit. Inclusion of a covered work
 251+in an aggregate does not cause this License to apply to the other
 252+parts of the aggregate.
 253+
 254+ 6. Conveying Non-Source Forms.
 255+
 256+ You may convey a covered work in object code form under the terms
 257+of sections 4 and 5, provided that you also convey the
 258+machine-readable Corresponding Source under the terms of this License,
 259+in one of these ways:
 260+
 261+ a) Convey the object code in, or embodied in, a physical product
 262+ (including a physical distribution medium), accompanied by the
 263+ Corresponding Source fixed on a durable physical medium
 264+ customarily used for software interchange.
 265+
 266+ b) Convey the object code in, or embodied in, a physical product
 267+ (including a physical distribution medium), accompanied by a
 268+ written offer, valid for at least three years and valid for as
 269+ long as you offer spare parts or customer support for that product
 270+ model, to give anyone who possesses the object code either (1) a
 271+ copy of the Corresponding Source for all the software in the
 272+ product that is covered by this License, on a durable physical
 273+ medium customarily used for software interchange, for a price no
 274+ more than your reasonable cost of physically performing this
 275+ conveying of source, or (2) access to copy the
 276+ Corresponding Source from a network server at no charge.
 277+
 278+ c) Convey individual copies of the object code with a copy of the
 279+ written offer to provide the Corresponding Source. This
 280+ alternative is allowed only occasionally and noncommercially, and
 281+ only if you received the object code with such an offer, in accord
 282+ with subsection 6b.
 283+
 284+ d) Convey the object code by offering access from a designated
 285+ place (gratis or for a charge), and offer equivalent access to the
 286+ Corresponding Source in the same way through the same place at no
 287+ further charge. You need not require recipients to copy the
 288+ Corresponding Source along with the object code. If the place to
 289+ copy the object code is a network server, the Corresponding Source
 290+ may be on a different server (operated by you or a third party)
 291+ that supports equivalent copying facilities, provided you maintain
 292+ clear directions next to the object code saying where to find the
 293+ Corresponding Source. Regardless of what server hosts the
 294+ Corresponding Source, you remain obligated to ensure that it is
 295+ available for as long as needed to satisfy these requirements.
 296+
 297+ e) Convey the object code using peer-to-peer transmission, provided
 298+ you inform other peers where the object code and Corresponding
 299+ Source of the work are being offered to the general public at no
 300+ charge under subsection 6d.
 301+
 302+ A separable portion of the object code, whose source code is excluded
 303+from the Corresponding Source as a System Library, need not be
 304+included in conveying the object code work.
 305+
 306+ A "User Product" is either (1) a "consumer product", which means any
 307+tangible personal property which is normally used for personal, family,
 308+or household purposes, or (2) anything designed or sold for incorporation
 309+into a dwelling. In determining whether a product is a consumer product,
 310+doubtful cases shall be resolved in favor of coverage. For a particular
 311+product received by a particular user, "normally used" refers to a
 312+typical or common use of that class of product, regardless of the status
 313+of the particular user or of the way in which the particular user
 314+actually uses, or expects or is expected to use, the product. A product
 315+is a consumer product regardless of whether the product has substantial
 316+commercial, industrial or non-consumer uses, unless such uses represent
 317+the only significant mode of use of the product.
 318+
 319+ "Installation Information" for a User Product means any methods,
 320+procedures, authorization keys, or other information required to install
 321+and execute modified versions of a covered work in that User Product from
 322+a modified version of its Corresponding Source. The information must
 323+suffice to ensure that the continued functioning of the modified object
 324+code is in no case prevented or interfered with solely because
 325+modification has been made.
 326+
 327+ If you convey an object code work under this section in, or with, or
 328+specifically for use in, a User Product, and the conveying occurs as
 329+part of a transaction in which the right of possession and use of the
 330+User Product is transferred to the recipient in perpetuity or for a
 331+fixed term (regardless of how the transaction is characterized), the
 332+Corresponding Source conveyed under this section must be accompanied
 333+by the Installation Information. But this requirement does not apply
 334+if neither you nor any third party retains the ability to install
 335+modified object code on the User Product (for example, the work has
 336+been installed in ROM).
 337+
 338+ The requirement to provide Installation Information does not include a
 339+requirement to continue to provide support service, warranty, or updates
 340+for a work that has been modified or installed by the recipient, or for
 341+the User Product in which it has been modified or installed. Access to a
 342+network may be denied when the modification itself materially and
 343+adversely affects the operation of the network or violates the rules and
 344+protocols for communication across the network.
 345+
 346+ Corresponding Source conveyed, and Installation Information provided,
 347+in accord with this section must be in a format that is publicly
 348+documented (and with an implementation available to the public in
 349+source code form), and must require no special password or key for
 350+unpacking, reading or copying.
 351+
 352+ 7. Additional Terms.
 353+
 354+ "Additional permissions" are terms that supplement the terms of this
 355+License by making exceptions from one or more of its conditions.
 356+Additional permissions that are applicable to the entire Program shall
 357+be treated as though they were included in this License, to the extent
 358+that they are valid under applicable law. If additional permissions
 359+apply only to part of the Program, that part may be used separately
 360+under those permissions, but the entire Program remains governed by
 361+this License without regard to the additional permissions.
 362+
 363+ When you convey a copy of a covered work, you may at your option
 364+remove any additional permissions from that copy, or from any part of
 365+it. (Additional permissions may be written to require their own
 366+removal in certain cases when you modify the work.) You may place
 367+additional permissions on material, added by you to a covered work,
 368+for which you have or can give appropriate copyright permission.
 369+
 370+ Notwithstanding any other provision of this License, for material you
 371+add to a covered work, you may (if authorized by the copyright holders of
 372+that material) supplement the terms of this License with terms:
 373+
 374+ a) Disclaiming warranty or limiting liability differently from the
 375+ terms of sections 15 and 16 of this License; or
 376+
 377+ b) Requiring preservation of specified reasonable legal notices or
 378+ author attributions in that material or in the Appropriate Legal
 379+ Notices displayed by works containing it; or
 380+
 381+ c) Prohibiting misrepresentation of the origin of that material, or
 382+ requiring that modified versions of such material be marked in
 383+ reasonable ways as different from the original version; or
 384+
 385+ d) Limiting the use for publicity purposes of names of licensors or
 386+ authors of the material; or
 387+
 388+ e) Declining to grant rights under trademark law for use of some
 389+ trade names, trademarks, or service marks; or
 390+
 391+ f) Requiring indemnification of licensors and authors of that
 392+ material by anyone who conveys the material (or modified versions of
 393+ it) with contractual assumptions of liability to the recipient, for
 394+ any liability that these contractual assumptions directly impose on
 395+ those licensors and authors.
 396+
 397+ All other non-permissive additional terms are considered "further
 398+restrictions" within the meaning of section 10. If the Program as you
 399+received it, or any part of it, contains a notice stating that it is
 400+governed by this License along with a term that is a further
 401+restriction, you may remove that term. If a license document contains
 402+a further restriction but permits relicensing or conveying under this
 403+License, you may add to a covered work material governed by the terms
 404+of that license document, provided that the further restriction does
 405+not survive such relicensing or conveying.
 406+
 407+ If you add terms to a covered work in accord with this section, you
 408+must place, in the relevant source files, a statement of the
 409+additional terms that apply to those files, or a notice indicating
 410+where to find the applicable terms.
 411+
 412+ Additional terms, permissive or non-permissive, may be stated in the
 413+form of a separately written license, or stated as exceptions;
 414+the above requirements apply either way.
 415+
 416+ 8. Termination.
 417+
 418+ You may not propagate or modify a covered work except as expressly
 419+provided under this License. Any attempt otherwise to propagate or
 420+modify it is void, and will automatically terminate your rights under
 421+this License (including any patent licenses granted under the third
 422+paragraph of section 11).
 423+
 424+ However, if you cease all violation of this License, then your
 425+license from a particular copyright holder is reinstated (a)
 426+provisionally, unless and until the copyright holder explicitly and
 427+finally terminates your license, and (b) permanently, if the copyright
 428+holder fails to notify you of the violation by some reasonable means
 429+prior to 60 days after the cessation.
 430+
 431+ Moreover, your license from a particular copyright holder is
 432+reinstated permanently if the copyright holder notifies you of the
 433+violation by some reasonable means, this is the first time you have
 434+received notice of violation of this License (for any work) from that
 435+copyright holder, and you cure the violation prior to 30 days after
 436+your receipt of the notice.
 437+
 438+ Termination of your rights under this section does not terminate the
 439+licenses of parties who have received copies or rights from you under
 440+this License. If your rights have been terminated and not permanently
 441+reinstated, you do not qualify to receive new licenses for the same
 442+material under section 10.
 443+
 444+ 9. Acceptance Not Required for Having Copies.
 445+
 446+ You are not required to accept this License in order to receive or
 447+run a copy of the Program. Ancillary propagation of a covered work
 448+occurring solely as a consequence of using peer-to-peer transmission
 449+to receive a copy likewise does not require acceptance. However,
 450+nothing other than this License grants you permission to propagate or
 451+modify any covered work. These actions infringe copyright if you do
 452+not accept this License. Therefore, by modifying or propagating a
 453+covered work, you indicate your acceptance of this License to do so.
 454+
 455+ 10. Automatic Licensing of Downstream Recipients.
 456+
 457+ Each time you convey a covered work, the recipient automatically
 458+receives a license from the original licensors, to run, modify and
 459+propagate that work, subject to this License. You are not responsible
 460+for enforcing compliance by third parties with this License.
 461+
 462+ An "entity transaction" is a transaction transferring control of an
 463+organization, or substantially all assets of one, or subdividing an
 464+organization, or merging organizations. If propagation of a covered
 465+work results from an entity transaction, each party to that
 466+transaction who receives a copy of the work also receives whatever
 467+licenses to the work the party's predecessor in interest had or could
 468+give under the previous paragraph, plus a right to possession of the
 469+Corresponding Source of the work from the predecessor in interest, if
 470+the predecessor has it or can get it with reasonable efforts.
 471+
 472+ You may not impose any further restrictions on the exercise of the
 473+rights granted or affirmed under this License. For example, you may
 474+not impose a license fee, royalty, or other charge for exercise of
 475+rights granted under this License, and you may not initiate litigation
 476+(including a cross-claim or counterclaim in a lawsuit) alleging that
 477+any patent claim is infringed by making, using, selling, offering for
 478+sale, or importing the Program or any portion of it.
 479+
 480+ 11. Patents.
 481+
 482+ A "contributor" is a copyright holder who authorizes use under this
 483+License of the Program or a work on which the Program is based. The
 484+work thus licensed is called the contributor's "contributor version".
 485+
 486+ A contributor's "essential patent claims" are all patent claims
 487+owned or controlled by the contributor, whether already acquired or
 488+hereafter acquired, that would be infringed by some manner, permitted
 489+by this License, of making, using, or selling its contributor version,
 490+but do not include claims that would be infringed only as a
 491+consequence of further modification of the contributor version. For
 492+purposes of this definition, "control" includes the right to grant
 493+patent sublicenses in a manner consistent with the requirements of
 494+this License.
 495+
 496+ Each contributor grants you a non-exclusive, worldwide, royalty-free
 497+patent license under the contributor's essential patent claims, to
 498+make, use, sell, offer for sale, import and otherwise run, modify and
 499+propagate the contents of its contributor version.
 500+
 501+ In the following three paragraphs, a "patent license" is any express
 502+agreement or commitment, however denominated, not to enforce a patent
 503+(such as an express permission to practice a patent or covenant not to
 504+sue for patent infringement). To "grant" such a patent license to a
 505+party means to make such an agreement or commitment not to enforce a
 506+patent against the party.
 507+
 508+ If you convey a covered work, knowingly relying on a patent license,
 509+and the Corresponding Source of the work is not available for anyone
 510+to copy, free of charge and under the terms of this License, through a
 511+publicly available network server or other readily accessible means,
 512+then you must either (1) cause the Corresponding Source to be so
 513+available, or (2) arrange to deprive yourself of the benefit of the
 514+patent license for this particular work, or (3) arrange, in a manner
 515+consistent with the requirements of this License, to extend the patent
 516+license to downstream recipients. "Knowingly relying" means you have
 517+actual knowledge that, but for the patent license, your conveying the
 518+covered work in a country, or your recipient's use of the covered work
 519+in a country, would infringe one or more identifiable patents in that
 520+country that you have reason to believe are valid.
 521+
 522+ If, pursuant to or in connection with a single transaction or
 523+arrangement, you convey, or propagate by procuring conveyance of, a
 524+covered work, and grant a patent license to some of the parties
 525+receiving the covered work authorizing them to use, propagate, modify
 526+or convey a specific copy of the covered work, then the patent license
 527+you grant is automatically extended to all recipients of the covered
 528+work and works based on it.
 529+
 530+ A patent license is "discriminatory" if it does not include within
 531+the scope of its coverage, prohibits the exercise of, or is
 532+conditioned on the non-exercise of one or more of the rights that are
 533+specifically granted under this License. You may not convey a covered
 534+work if you are a party to an arrangement with a third party that is
 535+in the business of distributing software, under which you make payment
 536+to the third party based on the extent of your activity of conveying
 537+the work, and under which the third party grants, to any of the
 538+parties who would receive the covered work from you, a discriminatory
 539+patent license (a) in connection with copies of the covered work
 540+conveyed by you (or copies made from those copies), or (b) primarily
 541+for and in connection with specific products or compilations that
 542+contain the covered work, unless you entered into that arrangement,
 543+or that patent license was granted, prior to 28 March 2007.
 544+
 545+ Nothing in this License shall be construed as excluding or limiting
 546+any implied license or other defenses to infringement that may
 547+otherwise be available to you under applicable patent law.
 548+
 549+ 12. No Surrender of Others' Freedom.
 550+
 551+ If conditions are imposed on you (whether by court order, agreement or
 552+otherwise) that contradict the conditions of this License, they do not
 553+excuse you from the conditions of this License. If you cannot convey a
 554+covered work so as to satisfy simultaneously your obligations under this
 555+License and any other pertinent obligations, then as a consequence you may
 556+not convey it at all. For example, if you agree to terms that obligate you
 557+to collect a royalty for further conveying from those to whom you convey
 558+the Program, the only way you could satisfy both those terms and this
 559+License would be to refrain entirely from conveying the Program.
 560+
 561+ 13. Use with the GNU Affero General Public License.
 562+
 563+ Notwithstanding any other provision of this License, you have
 564+permission to link or combine any covered work with a work licensed
 565+under version 3 of the GNU Affero General Public License into a single
 566+combined work, and to convey the resulting work. The terms of this
 567+License will continue to apply to the part which is the covered work,
 568+but the special requirements of the GNU Affero General Public License,
 569+section 13, concerning interaction through a network will apply to the
 570+combination as such.
 571+
 572+ 14. Revised Versions of this License.
 573+
 574+ The Free Software Foundation may publish revised and/or new versions of
 575+the GNU General Public License from time to time. Such new versions will
 576+be similar in spirit to the present version, but may differ in detail to
 577+address new problems or concerns.
 578+
 579+ Each version is given a distinguishing version number. If the
 580+Program specifies that a certain numbered version of the GNU General
 581+Public License "or any later version" applies to it, you have the
 582+option of following the terms and conditions either of that numbered
 583+version or of any later version published by the Free Software
 584+Foundation. If the Program does not specify a version number of the
 585+GNU General Public License, you may choose any version ever published
 586+by the Free Software Foundation.
 587+
 588+ If the Program specifies that a proxy can decide which future
 589+versions of the GNU General Public License can be used, that proxy's
 590+public statement of acceptance of a version permanently authorizes you
 591+to choose that version for the Program.
 592+
 593+ Later license versions may give you additional or different
 594+permissions. However, no additional obligations are imposed on any
 595+author or copyright holder as a result of your choosing to follow a
 596+later version.
 597+
 598+ 15. Disclaimer of Warranty.
 599+
 600+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
 601+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
 602+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
 603+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 604+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 605+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
 606+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
 607+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 608+
 609+ 16. Limitation of Liability.
 610+
 611+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 612+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
 613+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
 614+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
 615+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
 616+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
 617+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
 618+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
 619+SUCH DAMAGES.
 620+
 621+ 17. Interpretation of Sections 15 and 16.
 622+
 623+ If the disclaimer of warranty and limitation of liability provided
 624+above cannot be given local legal effect according to their terms,
 625+reviewing courts shall apply local law that most closely approximates
 626+an absolute waiver of all civil liability in connection with the
 627+Program, unless a warranty or assumption of liability accompanies a
 628+copy of the Program in return for a fee.
 629+
 630+ END OF TERMS AND CONDITIONS
 631+
 632+ How to Apply These Terms to Your New Programs
 633+
 634+ If you develop a new program, and you want it to be of the greatest
 635+possible use to the public, the best way to achieve this is to make it
 636+free software which everyone can redistribute and change under these terms.
 637+
 638+ To do so, attach the following notices to the program. It is safest
 639+to attach them to the start of each source file to most effectively
 640+state the exclusion of warranty; and each file should have at least
 641+the "copyright" line and a pointer to where the full notice is found.
 642+
 643+ <one line to give the program's name and a brief idea of what it does.>
 644+ Copyright (C) <year> <name of author>
 645+
 646+ This program is free software: you can redistribute it and/or modify
 647+ it under the terms of the GNU General Public License as published by
 648+ the Free Software Foundation, either version 3 of the License, or
 649+ (at your option) any later version.
 650+
 651+ This program is distributed in the hope that it will be useful,
 652+ but WITHOUT ANY WARRANTY; without even the implied warranty of
 653+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 654+ GNU General Public License for more details.
 655+
 656+ You should have received a copy of the GNU General Public License
 657+ along with this program. If not, see <http://www.gnu.org/licenses/>.
 658+
 659+Also add information on how to contact you by electronic and paper mail.
 660+
 661+ If the program does terminal interaction, make it output a short
 662+notice like this when it starts in an interactive mode:
 663+
 664+ <program> Copyright (C) <year> <name of author>
 665+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 666+ This is free software, and you are welcome to redistribute it
 667+ under certain conditions; type `show c' for details.
 668+
 669+The hypothetical commands `show w' and `show c' should show the appropriate
 670+parts of the General Public License. Of course, your program's commands
 671+might be different; for a GUI interface, you would use an "about box".
 672+
 673+ You should also get your employer (if you work as a programmer) or school,
 674+if any, to sign a "copyright disclaimer" for the program, if necessary.
 675+For more information on this, and how to apply and follow the GNU GPL, see
 676+<http://www.gnu.org/licenses/>.
 677+
 678+ The GNU General Public License does not permit incorporating your program
 679+into proprietary programs. If your program is a subroutine library, you
 680+may consider it more useful to permit linking proprietary applications with
 681+the library. If this is what you want to do, use the GNU Lesser General
 682+Public License instead of this License. But first, please read
 683+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/COPYING
___________________________________________________________________
Added: svn:eol-style
1684 + native
Index: tags/extensions/Survey/REL_0_1_2/api/ApiDeleteSurvey.php
@@ -0,0 +1,98 @@
 2+<?php
 3+
 4+/**
 5+ * API module to delete surveys.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file ApiDeleteSurvey.php
 10+ * @ingroup Survey
 11+ * @ingroup API
 12+ *
 13+ * @licence GNU GPL v3+
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+class ApiDeleteSurvey extends ApiBase {
 17+
 18+ public function __construct( $main, $action ) {
 19+ parent::__construct( $main, $action );
 20+ }
 21+
 22+ public function execute() {
 23+ global $wgUser;
 24+
 25+ if ( !$wgUser->isAllowed( 'surveyadmin' ) || $wgUser->isBlocked() ) {
 26+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
 27+ }
 28+
 29+ $params = $this->extractRequestParams();
 30+
 31+ $everythingOk = true;
 32+
 33+ foreach ( $params['ids'] as $id ) {
 34+ $surey = new Survey( array( 'id' => $id ) );
 35+ $everythingOk = $surey->removeFromDB() && $everythingOk;
 36+ }
 37+
 38+ $this->getResult()->addValue(
 39+ null,
 40+ 'success',
 41+ $everythingOk
 42+ );
 43+ }
 44+
 45+ public function needsToken() {
 46+ return true;
 47+ }
 48+
 49+ public function getTokenSalt() {
 50+ $params = $this->extractRequestParams();
 51+ return 'deletesurvey' . implode( '|', $params['ids'] );
 52+ }
 53+
 54+ public function mustBePosted() {
 55+ return true;
 56+ }
 57+
 58+ public function getAllowedParams() {
 59+ return array(
 60+ 'ids' => array(
 61+ ApiBase::PARAM_TYPE => 'integer',
 62+ ApiBase::PARAM_REQUIRED => true,
 63+ ApiBase::PARAM_ISMULTI => true,
 64+ ),
 65+ 'token' => null,
 66+ );
 67+ }
 68+
 69+ public function getParamDescription() {
 70+ return array(
 71+ 'ids' => 'The IDs of the surveys to delete',
 72+ 'token' => 'Edit token. You can get one of these through prop=info.',
 73+ );
 74+ }
 75+
 76+ public function getDescription() {
 77+ return array(
 78+ 'API module for deleting surveys.'
 79+ );
 80+ }
 81+
 82+ public function getPossibleErrors() {
 83+ return array_merge( parent::getPossibleErrors(), array(
 84+ array( 'missingparam', 'ids' ),
 85+ ) );
 86+ }
 87+
 88+ protected function getExamples() {
 89+ return array(
 90+ 'api.php?action=deletesurvey&ids=42',
 91+ 'api.php?action=deletesurvey&ids=4|2',
 92+ );
 93+ }
 94+
 95+ public function getVersion() {
 96+ return __CLASS__ . ': $Id$';
 97+ }
 98+
 99+}
Property changes on: tags/extensions/Survey/REL_0_1_2/api/ApiDeleteSurvey.php
___________________________________________________________________
Added: svn:keywords
1100 + Id
Added: svn:eol-style
2101 + native
Index: tags/extensions/Survey/REL_0_1_2/api/ApiSubmitSurvey.php
@@ -0,0 +1,118 @@
 2+<?php
 3+
 4+/**
 5+ * API module to submit surveys.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file ApiSubmitSurvey.php
 10+ * @ingroup Survey
 11+ * @ingroup API
 12+ *
 13+ * @licence GNU GPL v3+
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+class ApiSubmitSurvey extends ApiBase {
 17+
 18+ public function __construct( $main, $action ) {
 19+ parent::__construct( $main, $action );
 20+ }
 21+
 22+ public function execute() {
 23+ global $wgUser;
 24+
 25+ if ( !$wgUser->isAllowed( 'surveysubmit' ) || $wgUser->isBlocked() ) {
 26+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
 27+ }
 28+
 29+ $params = $this->extractRequestParams();
 30+
 31+ if ( !( isset( $params['id'] ) XOR isset( $params['name'] ) ) ) {
 32+ $this->dieUsage( wfMsgExt( 'survey-err-id-xor-name' ), 'id-xor-name' );
 33+ }
 34+
 35+ if ( isset( $params['name'] ) ) {
 36+ $survey = Survey::newFromName( $params['name'], null, false );
 37+
 38+ if ( $survey === false ) {
 39+ $this->dieUsage( wfMsgExt( 'survey-err-survey-name-unknown', 'parsemag', $params['name'] ), 'survey-name-unknown' );
 40+ }
 41+ } else {
 42+ $survey = Survey::newFromId( $params['id'], null, false );
 43+
 44+ if ( $survey === false ) {
 45+ $this->dieUsage( wfMsgExt( 'survey-err-survey-id-unknown', 'parsemag', $params['id'] ), 'survey-id-unknown' );
 46+ }
 47+ }
 48+
 49+ $submission = new SurveySubmission( array(
 50+ 'survey_id' => $survey->getId(),
 51+ 'page_id' => 0, // TODO
 52+ 'user_name' => $GLOBALS['wgUser']->getName(),
 53+ 'time' => wfTimestampNow()
 54+ ) );
 55+
 56+ foreach ( FormatJson::decode( $params['answers'] ) as $answer ) {
 57+ $submission->addAnswer( SurveyAnswer::newFromArray( (array)$answer ) );
 58+ }
 59+
 60+ $submission->writeToDB();
 61+ }
 62+
 63+ public function needsToken() {
 64+ return true;
 65+ }
 66+
 67+ public function getTokenSalt() {
 68+ return serialize( array( 'submitsurvey', $GLOBALS['wgUser']->getName() ) );
 69+ }
 70+
 71+ public function mustBePosted() {
 72+ return true;
 73+ }
 74+
 75+ public function getAllowedParams() {
 76+ return array(
 77+ 'id' => array(
 78+ ApiBase::PARAM_TYPE => 'integer',
 79+ ),
 80+ 'name' => array(
 81+ ApiBase::PARAM_TYPE => 'string',
 82+ ),
 83+ 'answers' => array(
 84+ ApiBase::PARAM_TYPE => 'string',
 85+ ),
 86+ 'token' => null,
 87+ );
 88+ }
 89+
 90+ public function getParamDescription() {
 91+ return array(
 92+ 'id' => 'The ID of the survey being submitted.',
 93+ 'name' => 'The name of the survey being submitted.',
 94+ 'token' => 'Edit token. You can get one of these through prop=info.',
 95+ );
 96+ }
 97+
 98+ public function getDescription() {
 99+ return array(
 100+ ''
 101+ );
 102+ }
 103+
 104+ public function getPossibleErrors() {
 105+ return array_merge( parent::getPossibleErrors(), array(
 106+ ) );
 107+ }
 108+
 109+ protected function getExamples() {
 110+ return array(
 111+ 'api.php?action=submitsurvey&',
 112+ );
 113+ }
 114+
 115+ public function getVersion() {
 116+ return __CLASS__ . ': $Id$';
 117+ }
 118+
 119+}
Property changes on: tags/extensions/Survey/REL_0_1_2/api/ApiSubmitSurvey.php
___________________________________________________________________
Added: svn:keywords
1120 + Id
Added: svn:eol-style
2121 + native
Index: tags/extensions/Survey/REL_0_1_2/api/ApiQuerySurveySubmissions.php
@@ -0,0 +1,146 @@
 2+<?php
 3+
 4+/**
 5+ * API module to get a list of survey submissions.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file ApiQuerySurveySubmissions.php
 10+ * @ingroup Surveys
 11+ * @ingroup API
 12+ *
 13+ * @licence GNU GPL v3+
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+class ApiQuerySurveySubmissions extends ApiQueryBase {
 17+
 18+ public function __construct( $main, $action ) {
 19+ parent::__construct( $main, $action, 'qs' );
 20+ }
 21+
 22+ /**
 23+ * Retrieve the special words from the database.
 24+ */
 25+ public function execute() {
 26+ global $wgUser;
 27+
 28+ if ( !$wgUser->isAllowed( 'surveyadmin' ) || $wgUser->isBlocked() ) {
 29+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
 30+ }
 31+
 32+ // Get the requests parameters.
 33+ $params = $this->extractRequestParams();
 34+
 35+ $starPropPosition = array_search( '*', $params['props'] );
 36+
 37+ if ( $starPropPosition !== false ) {
 38+ unset( $params['props'][$starPropPosition] );
 39+ $params['props'] = array_merge( $params['props'], SurveySubmission::getFieldNames() );
 40+ }
 41+
 42+ $params = array_filter( $params, function( $param ) { return !is_null( $param ); } );
 43+
 44+ $results = SurveySubmission::select(
 45+ $params['props'],
 46+ SurveySubmission::getValidFields( $params ),
 47+ array(
 48+ 'LIMIT' => $params['limit'] + 1,
 49+ 'ORDER BY' => SurveySubmission::getPrefixedField( 'id' ) . ' ASC'
 50+ )
 51+ );
 52+
 53+ $serializedResults = array();
 54+ $count = 0;
 55+
 56+ foreach ( $results as $result ) {
 57+ if ( ++$count > $params['limit'] ) {
 58+ // We've reached the one extra which shows that
 59+ // there are additional pages to be had. Stop here...
 60+ $this->setContinueEnumParameter( 'continue', $result->getId() );
 61+ break;
 62+ }
 63+
 64+ $serializedResults[] = $result->toArray();
 65+ }
 66+
 67+ $this->getResult()->setIndexedTagName( $serializedResults, 'submission' );
 68+
 69+ $this->getResult()->addValue(
 70+ null,
 71+ 'submissions',
 72+ $serializedResults
 73+ );
 74+ }
 75+
 76+ /**
 77+ * (non-PHPdoc)
 78+ * @see includes/api/ApiBase#getAllowedParams()
 79+ */
 80+ public function getAllowedParams() {
 81+ $params = array (
 82+ 'props' => array(
 83+ ApiBase::PARAM_TYPE => array_merge( SurveySubmission::getFieldNames(), array( '*' ) ),
 84+ ApiBase::PARAM_ISMULTI => true,
 85+ ApiBase::PARAM_DFLT => '*'
 86+ ),
 87+ 'limit' => array(
 88+ ApiBase::PARAM_DFLT => 20,
 89+ ApiBase::PARAM_TYPE => 'limit',
 90+ ApiBase::PARAM_MIN => 1,
 91+ ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
 92+ ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
 93+ ),
 94+ 'continue' => null,
 95+ );
 96+
 97+ return array_merge( SurveySubmission::getAPIParams( false ), $params );
 98+ }
 99+
 100+ /**
 101+ * (non-PHPdoc)
 102+ * @see includes/api/ApiBase#getParamDescription()
 103+ */
 104+ public function getParamDescription() {
 105+ $descs = array (
 106+ 'props' => 'Survey data to query',
 107+ 'continue' => 'Offset number from where to continue the query',
 108+ 'limit' => 'Max amount of words to return',
 109+ );
 110+
 111+ return array_merge( SurveySubmission::getFieldDescriptions(), $descs );
 112+ }
 113+
 114+ /**
 115+ * (non-PHPdoc)
 116+ * @see includes/api/ApiBase#getDescription()
 117+ */
 118+ public function getDescription() {
 119+ return 'API module for obatining survey submissions';
 120+ }
 121+
 122+ /**
 123+ * (non-PHPdoc)
 124+ * @see includes/api/ApiBase#getPossibleErrors()
 125+ */
 126+ public function getPossibleErrors() {
 127+ return array_merge( parent::getPossibleErrors(), array(
 128+ ) );
 129+ }
 130+
 131+ /**
 132+ * (non-PHPdoc)
 133+ * @see includes/api/ApiBase#getExamples()
 134+ */
 135+ protected function getExamples() {
 136+ return array (
 137+ 'api.php?action=query&list=surveysubmissions&qsid=42',
 138+ 'api.php?action=query&list=surveysubmissions&qssurvey_id=9001',
 139+ 'api.php?action=query&list=surveysubmissions&qsuser_name=Jeroen%20De%20Dauw&qsprops=survey_id|page_id|time',
 140+ );
 141+ }
 142+
 143+ public function getVersion() {
 144+ return __CLASS__ . ': $Id$';
 145+ }
 146+
 147+}
Property changes on: tags/extensions/Survey/REL_0_1_2/api/ApiQuerySurveySubmissions.php
___________________________________________________________________
Added: svn:keywords
1148 + Id
Added: svn:eol-style
2149 + native
Index: tags/extensions/Survey/REL_0_1_2/api/ApiEditSurvey.php
@@ -0,0 +1,119 @@
 2+<?php
 3+
 4+/**
 5+ * API module to edit surveys.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file ApiEditSurvey.php
 10+ * @ingroup Survey
 11+ * @ingroup API
 12+ *
 13+ * @licence GNU GPL v3+
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+class ApiEditSurvey extends ApiBase {
 17+
 18+ public function __construct( $main, $action ) {
 19+ parent::__construct( $main, $action );
 20+ }
 21+
 22+ public function execute() {
 23+ global $wgUser;
 24+
 25+ if ( !$wgUser->isAllowed( 'surveyadmin' ) || $wgUser->isBlocked() ) {
 26+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
 27+ }
 28+
 29+ $params = $this->extractRequestParams();
 30+
 31+ foreach ( $params['questions'] as &$question ) {
 32+ $question = SurveyQuestion::newFromUrlData( $question );
 33+ }
 34+
 35+ $survey = new Survey( Survey::getValidFields( $params, $params['id'] ) );
 36+
 37+ $this->getResult()->addValue(
 38+ null,
 39+ 'success',
 40+ $survey->writeToDB()
 41+ );
 42+
 43+ $this->getResult()->addValue(
 44+ 'survey',
 45+ 'id',
 46+ $survey->getId()
 47+ );
 48+
 49+ $this->getResult()->addValue(
 50+ 'survey',
 51+ 'name',
 52+ $survey->getField( 'name' )
 53+ );
 54+ }
 55+
 56+ public function needsToken() {
 57+ return true;
 58+ }
 59+
 60+ public function getTokenSalt() {
 61+ return 'editsurvey';
 62+ }
 63+
 64+ public function mustBePosted() {
 65+ return true;
 66+ }
 67+
 68+ public function getAllowedParams() {
 69+ $params = array(
 70+ 'id' => array(
 71+ ApiBase::PARAM_TYPE => 'integer',
 72+ ApiBase::PARAM_REQUIRED => true,
 73+ ),
 74+ 'questions' => array(
 75+ ApiBase::PARAM_TYPE => 'string',
 76+ ApiBase::PARAM_ISMULTI => true,
 77+ ApiBase::PARAM_REQUIRED => true,
 78+ ),
 79+ 'token' => null,
 80+ );
 81+
 82+ return array_merge( Survey::getAPIParams(), $params );
 83+ }
 84+
 85+ public function getParamDescription() {
 86+ return array(
 87+ 'id' => 'The ID of the survey to modify',
 88+ 'name' => 'The name of the survey',
 89+ 'enabled' => 'Enable the survey or not',
 90+ 'questions' => 'The questions that make up the survey',
 91+ 'token' => 'Edit token. You can get one of these through prop=info.',
 92+ );
 93+ }
 94+
 95+ public function getDescription() {
 96+ return array(
 97+ 'API module for editing a survey.'
 98+ );
 99+ }
 100+
 101+ public function getPossibleErrors() {
 102+ return array_merge( parent::getPossibleErrors(), array(
 103+ array( 'missingparam', 'id' ),
 104+ array( 'missingparam', 'name' ),
 105+ array( 'missingparam', 'enabled' ),
 106+ array( 'missingparam', 'questions' ),
 107+ ) );
 108+ }
 109+
 110+ protected function getExamples() {
 111+ return array(
 112+ 'api.php?action=editsurvey&',
 113+ );
 114+ }
 115+
 116+ public function getVersion() {
 117+ return __CLASS__ . ': $Id$';
 118+ }
 119+
 120+}
Property changes on: tags/extensions/Survey/REL_0_1_2/api/ApiEditSurvey.php
___________________________________________________________________
Added: svn:keywords
1121 + Id
Added: svn:eol-style
2122 + native
Index: tags/extensions/Survey/REL_0_1_2/api/ApiAddSurvey.php
@@ -0,0 +1,122 @@
 2+<?php
 3+
 4+/**
 5+ * API module to add surveys.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file ApiAddSurvey.php
 10+ * @ingroup Survey
 11+ * @ingroup API
 12+ *
 13+ * @licence GNU GPL v3+
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+class ApiAddSurvey extends ApiBase {
 17+
 18+ public function __construct( $main, $action ) {
 19+ parent::__construct( $main, $action );
 20+ }
 21+
 22+ public function execute() {
 23+ global $wgUser;
 24+
 25+ if ( !$wgUser->isAllowed( 'surveyadmin' ) || $wgUser->isBlocked() ) {
 26+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
 27+ }
 28+
 29+ $params = $this->extractRequestParams();
 30+
 31+ foreach ( $params['questions'] as &$question ) {
 32+ $question = SurveyQuestion::newFromUrlData( $question );
 33+ }
 34+
 35+ try {
 36+ $survey = new Survey( Survey::getValidFields( $params ) );
 37+ $success = $survey->writeToDB();
 38+ }
 39+ catch ( DBQueryError $ex ) {
 40+ if ( $ex->errno == 1062 ) {
 41+ $this->dieUsage( wfMsgExt( 'survey-err-duplicate-name', 'parsemag', $params['name'] ), 'duplicate-survey-name' );
 42+ } else {
 43+ throw $ex;
 44+ }
 45+ }
 46+
 47+ $this->getResult()->addValue(
 48+ null,
 49+ 'success',
 50+ $success
 51+ );
 52+
 53+ $this->getResult()->addValue(
 54+ 'survey',
 55+ 'id',
 56+ $survey->getId()
 57+ );
 58+
 59+ $this->getResult()->addValue(
 60+ 'survey',
 61+ 'name',
 62+ $survey->getField( 'name' )
 63+ );
 64+ }
 65+
 66+ public function needsToken() {
 67+ return true;
 68+ }
 69+
 70+ public function getTokenSalt() {
 71+ return 'addsurvey';
 72+ }
 73+
 74+ public function mustBePosted() {
 75+ return true;
 76+ }
 77+
 78+ public function getAllowedParams() {
 79+ $params = array(
 80+ 'questions' => array(
 81+ ApiBase::PARAM_TYPE => 'string',
 82+ ApiBase::PARAM_ISMULTI => true,
 83+ ApiBase::PARAM_DFLT => '',
 84+ ),
 85+ 'token' => null,
 86+ );
 87+
 88+ return array_merge( Survey::getAPIParams(), $params );
 89+ }
 90+
 91+ public function getParamDescription() {
 92+ return array(
 93+ 'name' => 'The name of the survey',
 94+ 'enabled' => 'Enable the survey or not',
 95+ 'questions' => 'The questions that make up the survey',
 96+ 'token' => 'Edit token. You can get one of these through prop=info.',
 97+ );
 98+ }
 99+
 100+ public function getDescription() {
 101+ return array(
 102+ 'API module for adding surveys.'
 103+ );
 104+ }
 105+
 106+ public function getPossibleErrors() {
 107+ return array_merge( parent::getPossibleErrors(), array(
 108+ array( 'missingparam', 'name' ),
 109+ array( 'missingparam', 'enabled' ),
 110+ ) );
 111+ }
 112+
 113+ protected function getExamples() {
 114+ return array(
 115+ 'api.php?action=addsurvey&name=My awesome survey&enabled=1&questions=',
 116+ );
 117+ }
 118+
 119+ public function getVersion() {
 120+ return __CLASS__ . ': $Id$';
 121+ }
 122+
 123+}
Property changes on: tags/extensions/Survey/REL_0_1_2/api/ApiAddSurvey.php
___________________________________________________________________
Added: svn:keywords
1124 + Id
Added: svn:eol-style
2125 + native
Index: tags/extensions/Survey/REL_0_1_2/api/ApiQuerySurveyAnswers.php
@@ -0,0 +1,146 @@
 2+<?php
 3+
 4+/**
 5+ * API module to get a list of survey answers.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file ApiQuerySurveyAnswers.php
 10+ * @ingroup Surveys
 11+ * @ingroup API
 12+ *
 13+ * @licence GNU GPL v3+
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+class ApiQuerySurveyAnswers extends ApiQueryBase {
 17+
 18+ public function __construct( $main, $action ) {
 19+ parent::__construct( $main, $action, 'qa' );
 20+ }
 21+
 22+ /**
 23+ * Retrieve the special words from the database.
 24+ */
 25+ public function execute() {
 26+ global $wgUser;
 27+
 28+ if ( !$wgUser->isAllowed( 'surveyadmin' ) || $wgUser->isBlocked() ) {
 29+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
 30+ }
 31+
 32+ // Get the requests parameters.
 33+ $params = $this->extractRequestParams();
 34+
 35+ $starPropPosition = array_search( '*', $params['props'] );
 36+
 37+ if ( $starPropPosition !== false ) {
 38+ unset( $params['props'][$starPropPosition] );
 39+ $params['props'] = array_merge( $params['props'], SurveyAnswer::getFieldNames() );
 40+ }
 41+
 42+ $params = array_filter( $params, function( $param ) { return !is_null( $param ); } );
 43+
 44+ $answers = SurveyAnswer::select(
 45+ $params['props'],
 46+ SurveyAnswer::getValidFields( $params ),
 47+ array(
 48+ 'LIMIT' => $params['limit'] + 1,
 49+ 'ORDER BY' => SurveyAnswer::getPrefixedField( 'id' ) . ' ASC'
 50+ )
 51+ );
 52+
 53+ $serializedAnswers = array();
 54+ $count = 0;
 55+
 56+ foreach ( $answers as $answer ) {
 57+ if ( ++$count > $params['limit'] ) {
 58+ // We've reached the one extra which shows that
 59+ // there are additional pages to be had. Stop here...
 60+ $this->setContinueEnumParameter( 'continue', $answer->getId() );
 61+ break;
 62+ }
 63+
 64+ $serializedAnswers[] = $answer->toArray();
 65+ }
 66+
 67+ $this->getResult()->setIndexedTagName( $serializedAnswers, 'answer' );
 68+
 69+ $this->getResult()->addValue(
 70+ null,
 71+ 'answers',
 72+ $serializedAnswers
 73+ );
 74+ }
 75+
 76+ /**
 77+ * (non-PHPdoc)
 78+ * @see includes/api/ApiBase#getAllowedParams()
 79+ */
 80+ public function getAllowedParams() {
 81+ $params = array (
 82+ 'props' => array(
 83+ ApiBase::PARAM_TYPE => array_merge( SurveyAnswer::getFieldNames(), array( '*' ) ),
 84+ ApiBase::PARAM_ISMULTI => true,
 85+ ApiBase::PARAM_DFLT => '*'
 86+ ),
 87+ 'limit' => array(
 88+ ApiBase::PARAM_DFLT => 20,
 89+ ApiBase::PARAM_TYPE => 'limit',
 90+ ApiBase::PARAM_MIN => 1,
 91+ ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
 92+ ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
 93+ ),
 94+ 'continue' => null,
 95+ );
 96+
 97+ return array_merge( SurveyAnswer::getAPIParams( false ), $params );
 98+ }
 99+
 100+ /**
 101+ * (non-PHPdoc)
 102+ * @see includes/api/ApiBase#getParamDescription()
 103+ */
 104+ public function getParamDescription() {
 105+ $descs = array (
 106+ 'props' => 'Survey data to query',
 107+ 'continue' => 'Offset number from where to continue the query',
 108+ 'limit' => 'Max amount of words to return',
 109+ );
 110+
 111+ return array_merge( SurveyAnswer::getFieldDescriptions(), $descs );
 112+ }
 113+
 114+ /**
 115+ * (non-PHPdoc)
 116+ * @see includes/api/ApiBase#getDescription()
 117+ */
 118+ public function getDescription() {
 119+ return 'API module for obatining survey answers';
 120+ }
 121+
 122+ /**
 123+ * (non-PHPdoc)
 124+ * @see includes/api/ApiBase#getPossibleErrors()
 125+ */
 126+ public function getPossibleErrors() {
 127+ return array_merge( parent::getPossibleErrors(), array(
 128+ ) );
 129+ }
 130+
 131+ /**
 132+ * (non-PHPdoc)
 133+ * @see includes/api/ApiBase#getExamples()
 134+ */
 135+ protected function getExamples() {
 136+ return array (
 137+ 'api.php?action=query&list=surveyanswers&qaid=42',
 138+ 'api.php?action=query&list=surveyanswers&qaid=42&qaprops=text|submission_id',
 139+ 'api.php?action=query&list=surveyanswers&qaquestion_id=9001&qaprops=text',
 140+ );
 141+ }
 142+
 143+ public function getVersion() {
 144+ return __CLASS__ . ': $Id$';
 145+ }
 146+
 147+}
Property changes on: tags/extensions/Survey/REL_0_1_2/api/ApiQuerySurveyAnswers.php
___________________________________________________________________
Added: svn:keywords
1148 + Id
Added: svn:eol-style
2149 + native
Index: tags/extensions/Survey/REL_0_1_2/api/ApiQuerySurveys.php
@@ -0,0 +1,209 @@
 2+<?php
 3+
 4+/**
 5+ * API module to get a list of surveys.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file ApiQuerySurveys.php
 10+ * @ingroup Surveys
 11+ * @ingroup API
 12+ *
 13+ * @licence GNU GPL v3+
 14+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 15+ */
 16+class ApiQuerySurveys extends ApiQueryBase {
 17+
 18+ public function __construct( $main, $action ) {
 19+ parent::__construct( $main, $action, 'su' );
 20+ }
 21+
 22+ /**
 23+ * Retrieve the special words from the database.
 24+ */
 25+ public function execute() {
 26+ global $wgUser;
 27+
 28+ if ( !$wgUser->isAllowed( 'surveysubmit' ) || $wgUser->isBlocked() ) {
 29+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
 30+ }
 31+
 32+ // Get the requests parameters.
 33+ $params = $this->extractRequestParams();
 34+
 35+ if ( !( ( isset( $params['ids'] ) && count( $params['ids'] ) > 0 )
 36+ XOR ( isset( $params['names'] ) && count( $params['names'] ) > 0 )
 37+ ) ) {
 38+ $this->dieUsage( wfMsg( 'survey-err-ids-xor-names' ), 'ids-xor-names' );
 39+ }
 40+
 41+ $this->addTables( 'surveys' );
 42+
 43+ $starPropPosition = array_search( '*', $params['props'] );
 44+
 45+ if ( $starPropPosition !== false ) {
 46+ unset( $params['props'][$starPropPosition] );
 47+ $params['props'] = array_merge( $params['props'], Survey::getFieldNames() );
 48+ }
 49+
 50+ $fields = array_merge( array( 'id' ), $params['props'] );
 51+
 52+ $this->addFields( Survey::getPrefixedFields( $fields ) );
 53+
 54+ if ( isset( $params['ids'] ) ) {
 55+ $this->addWhere( array( 'survey_id' => $params['ids'] ) );
 56+ } else {
 57+ $this->addWhere( array( 'survey_name' => $params['names'] ) );
 58+ }
 59+
 60+ if ( !$GLOBALS['wgUser']->isAllowed( 'surveyadmin' ) ) {
 61+ $this->addWhere( array( 'survey_enabled' => 1 ) );
 62+ }
 63+ else if ( isset( $params['enabled'] ) ) {
 64+ $this->addWhere( array( 'survey_enabled' => $params['enabled'] ) );
 65+ }
 66+
 67+ if ( isset( $params['continue'] ) ) {
 68+ $this->addWhere( 'survey_id >= ' . wfGetDB( DB_SLAVE )->addQuotes( $params['continue'] ) );
 69+ }
 70+
 71+ $this->addOption( 'LIMIT', $params['limit'] + 1 );
 72+ $this->addOption( 'ORDER BY', 'survey_id ASC' );
 73+
 74+ $surveys = $this->select( __METHOD__ );
 75+ $count = 0;
 76+ $resultSurveys = array();
 77+
 78+ foreach ( $surveys as $survey ) {
 79+ if ( ++$count > $params['limit'] ) {
 80+ // We've reached the one extra which shows that
 81+ // there are additional pages to be had. Stop here...
 82+ $this->setContinueEnumParameter( 'continue', $survey->survey_id );
 83+ break;
 84+ }
 85+
 86+ $surveyObject = Survey::newFromDBResult( $survey );
 87+
 88+ if ( $params['incquestions'] ) {
 89+ $surveyObject->loadQuestionsFromDB();
 90+ }
 91+
 92+ $resultSurveys[] = $this->getSurveyData( $surveyObject->toArray( $fields ) );
 93+ }
 94+
 95+ $this->getResult()->setIndexedTagName( $resultSurveys, 'survey' );
 96+
 97+ $this->getResult()->addValue(
 98+ null,
 99+ 'surveys',
 100+ $resultSurveys
 101+ );
 102+ }
 103+
 104+ /**
 105+ *
 106+ *
 107+ * @since 0.1
 108+ *
 109+ * @param array $survey
 110+ *
 111+ * @return $survey
 112+ */
 113+ protected function getSurveyData( array $survey ) {
 114+ foreach ( $survey['questions'] as $nr => $question ) {
 115+ $this->getResult()->setIndexedTagName( $survey['questions'][$nr], 'answer' );
 116+ }
 117+
 118+ $this->getResult()->setIndexedTagName( $survey['questions'], 'question' );
 119+
 120+ return $survey;
 121+ }
 122+
 123+ /**
 124+ * (non-PHPdoc)
 125+ * @see includes/api/ApiBase#getAllowedParams()
 126+ */
 127+ public function getAllowedParams() {
 128+ return array (
 129+ 'ids' => array(
 130+ ApiBase::PARAM_TYPE => 'integer',
 131+ ApiBase::PARAM_ISMULTI => true,
 132+ ),
 133+ 'names' => array(
 134+ ApiBase::PARAM_TYPE => 'string',
 135+ ApiBase::PARAM_ISMULTI => true,
 136+ ),
 137+ 'props' => array(
 138+ ApiBase::PARAM_TYPE => array_merge( Survey::getFieldNames(), array( '*' ) ),
 139+ ApiBase::PARAM_ISMULTI => true,
 140+ ApiBase::PARAM_DFLT => 'id|name|enabled'
 141+ ),
 142+ 'incquestions' => array(
 143+ ApiBase::PARAM_TYPE => 'integer',
 144+ ApiBase::PARAM_DFLT => '0',
 145+ ),
 146+ 'enabled' => array(
 147+ ApiBase::PARAM_TYPE => 'integer',
 148+ ),
 149+ 'limit' => array(
 150+ ApiBase::PARAM_DFLT => 20,
 151+ ApiBase::PARAM_TYPE => 'limit',
 152+ ApiBase::PARAM_MIN => 1,
 153+ ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
 154+ ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
 155+ ),
 156+ 'continue' => null,
 157+ );
 158+
 159+ }
 160+
 161+ /**
 162+ * (non-PHPdoc)
 163+ * @see includes/api/ApiBase#getParamDescription()
 164+ */
 165+ public function getParamDescription() {
 166+ return array (
 167+ 'ids' => 'The IDs of the surveys to return',
 168+ 'names' => 'The names of the surveys to return',
 169+ 'incquestions' => 'Include the questions of the surveys or not',
 170+ 'enabled' => 'Enabled state to filter on',
 171+ 'props' => 'Survey data to query',
 172+ 'continue' => 'Offset number from where to continue the query',
 173+ 'limit' => 'Max amount of words to return',
 174+ );
 175+ }
 176+
 177+ /**
 178+ * (non-PHPdoc)
 179+ * @see includes/api/ApiBase#getDescription()
 180+ */
 181+ public function getDescription() {
 182+ return 'API module for obatining surveys and optionaly their questions';
 183+ }
 184+
 185+ /**
 186+ * (non-PHPdoc)
 187+ * @see includes/api/ApiBase#getPossibleErrors()
 188+ */
 189+ public function getPossibleErrors() {
 190+ return array_merge( parent::getPossibleErrors(), array(
 191+ array( 'surveyids', 'name' ),
 192+ ) );
 193+ }
 194+
 195+ /**
 196+ * (non-PHPdoc)
 197+ * @see includes/api/ApiBase#getExamples()
 198+ */
 199+ protected function getExamples() {
 200+ return array (
 201+ 'api.php?action=query&list=surveys&suids=4|2',
 202+ 'api.php?action=query&list=surveys&suenabled=1&suprops=id|name',
 203+ );
 204+ }
 205+
 206+ public function getVersion() {
 207+ return __CLASS__ . ': $Id$';
 208+ }
 209+
 210+}
Property changes on: tags/extensions/Survey/REL_0_1_2/api/ApiQuerySurveys.php
___________________________________________________________________
Added: svn:keywords
1211 + Id
Added: svn:eol-style
2212 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.tag.js
@@ -0,0 +1,98 @@
 2+/**
 3+ * JavasSript for the Survey MediaWiki extension.
 4+ * @see https://secure.wikimedia.org/wikipedia/mediawiki/wiki/Extension:Survey
 5+ *
 6+ * @licence GNU GPL v3 or later
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+(function( $, survey ) {
 11+
 12+ function getCookieName( options ) {
 13+ return ( typeof options.id !== 'undefined' ) ?
 14+ 'survey-id-' + options.id
 15+ : 'survey-name-' + options.name;
 16+ }
 17+
 18+ function getCookie( options ) {
 19+ var cookie = $.cookie( getCookieName( options ) );
 20+ survey.log( 'read "' + cookie + '" from cookie ' + getCookieName( options ) );
 21+ return cookie;
 22+ }
 23+
 24+ function setCookie( options, cookieValue ) {
 25+ var date = new Date();
 26+ date.setTime( date.getTime() + options.expiry * 1000 );
 27+ $.cookie( getCookieName( options ), cookieValue, { 'expires': date, 'path': '/' } );
 28+ survey.log( 'wrote "' + cookieValue + '" to cookie ' + getCookieName( options ) );
 29+ }
 30+
 31+ function hasCookie( options ) {
 32+ return getCookie( options ) !== null;
 33+ }
 34+
 35+ function winsLottery( options ) {
 36+ var rand = Math.random();
 37+ survey.log( 'doLottery: ' + rand + ' < ' + options.ratio );
 38+ return rand < options.ratio;
 39+ }
 40+
 41+ function initCookieSurvey( options, $tag ) {
 42+ if ( hasCookie( options ) || options.ratio === 1 || winsLottery( options ) ) {
 43+ var cookie = getCookie( options );
 44+
 45+ if ( cookie !== 'done' ) {
 46+ if ( ( options.pages === 0 || parseInt( cookie, 10 ) >= options.pages ) ) {
 47+ $tag.mwSurvey( options );
 48+ setCookie( options, 'done' );
 49+ }
 50+ else if ( options.pages !== 0 ) {
 51+ var nr = parseInt( getCookie( options ), 10 );
 52+ setCookie( options, ( isNaN( nr ) ? 0 : nr ) + 1 );
 53+ }
 54+ }
 55+ }
 56+ else {
 57+ setCookie( options, 'done' );
 58+ }
 59+ }
 60+
 61+ function initTag( $tag ) {
 62+ var ratioAttr = $tag.attr( 'survey-data-ratio' );
 63+ var expiryAttr = $tag.attr( 'survey-data-expiry' );
 64+ var pagesAttr = $tag.attr( 'survey-data-min-pages' );
 65+
 66+ var options = {
 67+ 'ratio': typeof ratioAttr === 'undefined' ? 1 : parseFloat( ratioAttr ) / 100,
 68+ 'cookie': $tag.attr( 'survey-data-cookie' ) !== 'no',
 69+ 'expiry': typeof expiryAttr === 'undefined' ? 60 * 60 * 24 * 30 : parseInt( expiryAttr, 10 ),
 70+ 'pages': typeof pagesAttr === 'undefined' ? 0 : parseInt( pagesAttr, 10 )
 71+ };
 72+
 73+ if ( $tag.attr( 'survey-data-id' ) ) {
 74+ options.id = $tag.attr( 'survey-data-id' );
 75+ } else if ( $tag.attr( 'survey-data-name' ) ) {
 76+ options.name = $tag.attr( 'survey-data-name' );
 77+ }
 78+ else {
 79+ // TODO
 80+ return;
 81+ }
 82+
 83+ if ( options.cookie ) {
 84+ initCookieSurvey( options, $tag );
 85+ }
 86+ else {
 87+ $tag.mwSurvey( options );
 88+ }
 89+ }
 90+
 91+ $( document ).ready( function() {
 92+
 93+ $( '.surveytag' ).each( function( index, domElement ) {
 94+ initTag( $( domElement ) );
 95+ } );
 96+
 97+ } );
 98+
 99+})( jQuery, window.survey );
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.tag.js
___________________________________________________________________
Added: svn:eol-style
1100 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.special.survey.js
@@ -0,0 +1,186 @@
 2+/**
 3+ * JavasSript for the Survey MediaWiki extension.
 4+ * @see https://secure.wikimedia.org/wikipedia/mediawiki/wiki/Extension:Survey
 5+ *
 6+ * @licence GNU GPL v3 or later
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+(function( $, mw, survey ) { $( document ).ready( function() {
 11+
 12+ var _this = this;
 13+
 14+ var $table = null;
 15+ var newQuestionNr = 0;
 16+ var questionNr = 0;
 17+
 18+ function addAddQuestionRow() {
 19+ var $tr = $( '<tr />' ).attr( {
 20+ 'class': 'add-question'
 21+ } );
 22+
 23+ $table.append( $tr );
 24+
 25+ $tr.append( $( '<td />' ).attr( { 'class': 'mw-label question-label' } ).html(
 26+ '' //$( '<label />' ).text( mw.msg( 'survey-special-label-addquestion' ) )
 27+ ) );
 28+
 29+ $tr.append( $( '<td />' ).attr( { 'class': 'mw-input' } ).html(
 30+ '' //getQuestionInput( { 'id': 'new', 'answers': [], 'type': 0 } )
 31+ ).append( $( '<button />' ).button( { 'label': mw.msg( 'survey-special-label-add-first' ) } )
 32+ .click( function() {
 33+ $( this ).button( { 'label': mw.msg( 'survey-special-label-add-another' ) } );
 34+ onAddQuestionRequest();
 35+ return false;
 36+ } )
 37+ ) );
 38+//
 39+// $( '#survey-question-text-new' ).keypress( function( event ) {
 40+// if ( event.which == '13' ) {
 41+// event.preventDefault();
 42+// onAddQuestionRequest();
 43+// }
 44+// } );
 45+ };
 46+
 47+ function addQuestion( question ) {
 48+ var $tr = $( '<tr />' ).attr( {
 49+ 'class': 'mw-htmlform-field-SurveyQuestionField'
 50+ } );
 51+
 52+ $tr.append( $( '<td />' ).attr( { 'class': 'mw-label question-label' } ).html(
 53+ $( '<label />' ).text( mw.msg( 'survey-question-label-nr', ++questionNr ) )
 54+ ) );
 55+
 56+ $tr.append( $( '<td />' ).attr( { 'class': 'mw-input' } ).html(
 57+ getQuestionInput( question )
 58+ .append( '<br />' )
 59+ .append( $( '<button />' ).button( { 'label': mw.msg( 'survey-special-remove' ) } )
 60+ .click( function() {
 61+ if ( confirm( mw.msg( 'survey-special-remove-confirm' ) ) ) {
 62+ removeQuestion( question );
 63+ }
 64+
 65+ return false;
 66+ } )
 67+ )
 68+ ) );
 69+
 70+ $table.find( '.add-question' ).before( $tr );
 71+ };
 72+
 73+ function getQuestionInput( question ) {
 74+ var $input = $( '<div />' ).attr( {
 75+ 'border': '1px solid black',
 76+ 'id': 'survey-question-div-' + question.id
 77+ } );
 78+
 79+ var answerSelector = new survey.answerSelector( {
 80+ 'visible': survey.question.typeHasAnswers( parseInt( question.type ) ),
 81+ 'attr': {
 82+ 'rows': 2,
 83+ 'cols': 80,
 84+ 'id': 'survey-question-answers-' + question.id,
 85+ 'name': 'survey-question-answers-' + question.id
 86+ },
 87+ 'answers': question.answers
 88+ } );
 89+
 90+ $input.append( $( '<label />' ).attr( {
 91+ 'for': 'survey-question-text-' + question.id
 92+ } ).text( mw.msg( 'survey-special-label-text' ) ) );
 93+
 94+ $input.append( '<br />' );
 95+
 96+ $input.append( $( '<textarea />' ).attr( {
 97+ 'rows': 2,
 98+ 'cols': 80,
 99+ 'id': 'survey-question-text-' + question.id,
 100+ 'name': 'survey-question-text-' + question.id
 101+ } ).val( question.text ) );
 102+
 103+ $input.append( '<br />' );
 104+
 105+ $input.append( $( '<label />' ).attr( {
 106+ 'for': 'survey-question-type-' + question.id
 107+ } ).text( mw.msg( 'survey-special-label-type' ) ) );
 108+
 109+ $input.append( survey.question.getTypeSelector(
 110+ question.type,
 111+ {
 112+ 'id': 'survey-question-type-' + question.id,
 113+ 'name': 'survey-question-type-' + question.id
 114+ },
 115+ function( newValue ) {
 116+ answerSelector.setVisible( survey.question.typeHasAnswers( parseInt( newValue ) ) );
 117+ }
 118+ ) );
 119+
 120+ // Not implemented in actual survey yet, so don't show for now.
 121+// $required = $( '<input />' ).attr( {
 122+// 'id': 'survey-question-required-' + question.id,
 123+// 'name': 'survey-question-required-' + question.id,
 124+// 'type': 'checkbox',
 125+// } );
 126+//
 127+// if ( question.required ) {
 128+// $required.attr( 'checked', 'checked' );
 129+// }
 130+//
 131+// $input.append( $required );
 132+//
 133+// $input.append( $( '<label />' ).attr( {
 134+// 'for': 'survey-question-required-' + question.id
 135+// } ).text( mw.msg( 'survey-special-label-required' ) ) );
 136+
 137+ $input.append( answerSelector.getHtml() );
 138+
 139+ return $input;
 140+ };
 141+
 142+ function removeQuestion( question ) {
 143+ $( '#survey-question-div-' + question.id ).closest( 'tr' ).slideUp( 'fast', function() { $( this ).remove(); } )
 144+ };
 145+
 146+ function onAddQuestionRequest() {
 147+ addQuestion( {
 148+ 'text': '', // $( '#survey-question-text-new' ).val(),
 149+ 'required': false, //!!$( '#survey-question-required-new' ).attr( 'checked' ),
 150+ 'type': 0, // $( '#survey-question-type-new' ).val(),
 151+ 'id': 'new-' + ++newQuestionNr,
 152+ 'answers': [] //$( '#survey-question-answers-new' ).val().split( '\n' )
 153+ } );
 154+ $( '#survey-question-text-new-' + newQuestionNr ).focus().select();
 155+ $( 'html' ).animate( { scrollTop: $( document ).height() }, 'fast' );
 156+ };
 157+
 158+ function setup() {
 159+ $table = $( '#survey-title' ).closest( 'tbody' );
 160+
 161+ $table.append( '<tr><td colspan="2"><hr /></td></tr>' );
 162+
 163+ addAddQuestionRow();
 164+
 165+ $table.append( '<tr><td colspan="2"><hr /></td></tr>' );
 166+
 167+ $( '.survey-question-data' ).each( function( index, domElement ) {
 168+ $this = $( domElement );
 169+
 170+ addQuestion( {
 171+ 'text': $this.attr( 'data-text' ),
 172+ 'default': $this.attr( 'data-default' ),
 173+ 'required': $this.attr( 'data-required' ) == '1',
 174+ 'id': $this.attr( 'data-id' ),
 175+ 'type': $this.attr( 'data-type' ),
 176+ 'answers': eval( $this.attr( 'data-answers' ) )
 177+ } );
 178+ } );
 179+
 180+ $( '.mw-htmlform-submit' ).button();
 181+ $( '#cancelEdit' ).button();
 182+
 183+ };
 184+
 185+ setup();
 186+
 187+} ); })( jQuery, window.mediaWiki, window.survey );
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.special.survey.js
___________________________________________________________________
Added: svn:eol-style
1188 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/jquery.survey.css
@@ -0,0 +1,12 @@
 2+@CHARSET "UTF-8";
 3+
 4+.survey-textarea {
 5+ width: 80%
 6+}
 7+
 8+div.survey-question {
 9+ border-top: 1px solid #ddd;
 10+ padding-top: 10px;
 11+ padding-bottom: 10px;
 12+ font-size: smaller;
 13+}
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/jquery.survey.css
___________________________________________________________________
Added: svn:eol-style
114 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/JSON.js
@@ -0,0 +1,480 @@
 2+/*
 3+ http://www.JSON.org/json2.js
 4+ 2011-02-23
 5+
 6+ Public Domain.
 7+
 8+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 9+
 10+ See http://www.JSON.org/js.html
 11+
 12+
 13+ This code should be minified before deployment.
 14+ See http://javascript.crockford.com/jsmin.html
 15+
 16+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
 17+ NOT CONTROL.
 18+
 19+
 20+ This file creates a global JSON object containing two methods: stringify
 21+ and parse.
 22+
 23+ JSON.stringify(value, replacer, space)
 24+ value any JavaScript value, usually an object or array.
 25+
 26+ replacer an optional parameter that determines how object
 27+ values are stringified for objects. It can be a
 28+ function or an array of strings.
 29+
 30+ space an optional parameter that specifies the indentation
 31+ of nested structures. If it is omitted, the text will
 32+ be packed without extra whitespace. If it is a number,
 33+ it will specify the number of spaces to indent at each
 34+ level. If it is a string (such as '\t' or '&nbsp;'),
 35+ it contains the characters used to indent at each level.
 36+
 37+ This method produces a JSON text from a JavaScript value.
 38+
 39+ When an object value is found, if the object contains a toJSON
 40+ method, its toJSON method will be called and the result will be
 41+ stringified. A toJSON method does not serialize: it returns the
 42+ value represented by the name/value pair that should be serialized,
 43+ or undefined if nothing should be serialized. The toJSON method
 44+ will be passed the key associated with the value, and this will be
 45+ bound to the value
 46+
 47+ For example, this would serialize Dates as ISO strings.
 48+
 49+ Date.prototype.toJSON = function (key) {
 50+ function f(n) {
 51+ // Format integers to have at least two digits.
 52+ return n < 10 ? '0' + n : n;
 53+ }
 54+
 55+ return this.getUTCFullYear() + '-' +
 56+ f(this.getUTCMonth() + 1) + '-' +
 57+ f(this.getUTCDate()) + 'T' +
 58+ f(this.getUTCHours()) + ':' +
 59+ f(this.getUTCMinutes()) + ':' +
 60+ f(this.getUTCSeconds()) + 'Z';
 61+ };
 62+
 63+ You can provide an optional replacer method. It will be passed the
 64+ key and value of each member, with this bound to the containing
 65+ object. The value that is returned from your method will be
 66+ serialized. If your method returns undefined, then the member will
 67+ be excluded from the serialization.
 68+
 69+ If the replacer parameter is an array of strings, then it will be
 70+ used to select the members to be serialized. It filters the results
 71+ such that only members with keys listed in the replacer array are
 72+ stringified.
 73+
 74+ Values that do not have JSON representations, such as undefined or
 75+ functions, will not be serialized. Such values in objects will be
 76+ dropped; in arrays they will be replaced with null. You can use
 77+ a replacer function to replace those with JSON values.
 78+ JSON.stringify(undefined) returns undefined.
 79+
 80+ The optional space parameter produces a stringification of the
 81+ value that is filled with line breaks and indentation to make it
 82+ easier to read.
 83+
 84+ If the space parameter is a non-empty string, then that string will
 85+ be used for indentation. If the space parameter is a number, then
 86+ the indentation will be that many spaces.
 87+
 88+ Example:
 89+
 90+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
 91+ // text is '["e",{"pluribus":"unum"}]'
 92+
 93+
 94+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
 95+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
 96+
 97+ text = JSON.stringify([new Date()], function (key, value) {
 98+ return this[key] instanceof Date ?
 99+ 'Date(' + this[key] + ')' : value;
 100+ });
 101+ // text is '["Date(---current time---)"]'
 102+
 103+
 104+ JSON.parse(text, reviver)
 105+ This method parses a JSON text to produce an object or array.
 106+ It can throw a SyntaxError exception.
 107+
 108+ The optional reviver parameter is a function that can filter and
 109+ transform the results. It receives each of the keys and values,
 110+ and its return value is used instead of the original value.
 111+ If it returns what it received, then the structure is not modified.
 112+ If it returns undefined then the member is deleted.
 113+
 114+ Example:
 115+
 116+ // Parse the text. Values that look like ISO date strings will
 117+ // be converted to Date objects.
 118+
 119+ myData = JSON.parse(text, function (key, value) {
 120+ var a;
 121+ if (typeof value === 'string') {
 122+ a =
 123+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
 124+ if (a) {
 125+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
 126+ +a[5], +a[6]));
 127+ }
 128+ }
 129+ return value;
 130+ });
 131+
 132+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
 133+ var d;
 134+ if (typeof value === 'string' &&
 135+ value.slice(0, 5) === 'Date(' &&
 136+ value.slice(-1) === ')') {
 137+ d = new Date(value.slice(5, -1));
 138+ if (d) {
 139+ return d;
 140+ }
 141+ }
 142+ return value;
 143+ });
 144+
 145+
 146+ This is a reference implementation. You are free to copy, modify, or
 147+ redistribute.
 148+*/
 149+
 150+/*jslint evil: true, strict: false, regexp: false */
 151+
 152+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
 153+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
 154+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
 155+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
 156+ test, toJSON, toString, valueOf
 157+*/
 158+
 159+
 160+// Create a JSON object only if one does not already exist. We create the
 161+// methods in a closure to avoid creating global variables.
 162+
 163+var JSON;
 164+if (!JSON) {
 165+ JSON = {};
 166+}
 167+
 168+(function () {
 169+ "use strict";
 170+
 171+ function f(n) {
 172+ // Format integers to have at least two digits.
 173+ return n < 10 ? '0' + n : n;
 174+ }
 175+
 176+ if (typeof Date.prototype.toJSON !== 'function') {
 177+
 178+ Date.prototype.toJSON = function (key) {
 179+
 180+ return isFinite(this.valueOf()) ?
 181+ this.getUTCFullYear() + '-' +
 182+ f(this.getUTCMonth() + 1) + '-' +
 183+ f(this.getUTCDate()) + 'T' +
 184+ f(this.getUTCHours()) + ':' +
 185+ f(this.getUTCMinutes()) + ':' +
 186+ f(this.getUTCSeconds()) + 'Z' : null;
 187+ };
 188+
 189+ String.prototype.toJSON =
 190+ Number.prototype.toJSON =
 191+ Boolean.prototype.toJSON = function (key) {
 192+ return this.valueOf();
 193+ };
 194+ }
 195+
 196+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 197+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 198+ gap,
 199+ indent,
 200+ meta = { // table of character substitutions
 201+ '\b': '\\b',
 202+ '\t': '\\t',
 203+ '\n': '\\n',
 204+ '\f': '\\f',
 205+ '\r': '\\r',
 206+ '"' : '\\"',
 207+ '\\': '\\\\'
 208+ },
 209+ rep;
 210+
 211+
 212+ function quote(string) {
 213+
 214+// If the string contains no control characters, no quote characters, and no
 215+// backslash characters, then we can safely slap some quotes around it.
 216+// Otherwise we must also replace the offending characters with safe escape
 217+// sequences.
 218+
 219+ escapable.lastIndex = 0;
 220+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
 221+ var c = meta[a];
 222+ return typeof c === 'string' ? c :
 223+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 224+ }) + '"' : '"' + string + '"';
 225+ }
 226+
 227+
 228+ function str(key, holder) {
 229+
 230+// Produce a string from holder[key].
 231+
 232+ var i, // The loop counter.
 233+ k, // The member key.
 234+ v, // The member value.
 235+ length,
 236+ mind = gap,
 237+ partial,
 238+ value = holder[key];
 239+
 240+// If the value has a toJSON method, call it to obtain a replacement value.
 241+
 242+ if (value && typeof value === 'object' &&
 243+ typeof value.toJSON === 'function') {
 244+ value = value.toJSON(key);
 245+ }
 246+
 247+// If we were called with a replacer function, then call the replacer to
 248+// obtain a replacement value.
 249+
 250+ if (typeof rep === 'function') {
 251+ value = rep.call(holder, key, value);
 252+ }
 253+
 254+// What happens next depends on the value's type.
 255+
 256+ switch (typeof value) {
 257+ case 'string':
 258+ return quote(value);
 259+
 260+ case 'number':
 261+
 262+// JSON numbers must be finite. Encode non-finite numbers as null.
 263+
 264+ return isFinite(value) ? String(value) : 'null';
 265+
 266+ case 'boolean':
 267+ case 'null':
 268+
 269+// If the value is a boolean or null, convert it to a string. Note:
 270+// typeof null does not produce 'null'. The case is included here in
 271+// the remote chance that this gets fixed someday.
 272+
 273+ return String(value);
 274+
 275+// If the type is 'object', we might be dealing with an object or an array or
 276+// null.
 277+
 278+ case 'object':
 279+
 280+// Due to a specification blunder in ECMAScript, typeof null is 'object',
 281+// so watch out for that case.
 282+
 283+ if (!value) {
 284+ return 'null';
 285+ }
 286+
 287+// Make an array to hold the partial results of stringifying this object value.
 288+
 289+ gap += indent;
 290+ partial = [];
 291+
 292+// Is the value an array?
 293+
 294+ if (Object.prototype.toString.apply(value) === '[object Array]') {
 295+
 296+// The value is an array. Stringify every element. Use null as a placeholder
 297+// for non-JSON values.
 298+
 299+ length = value.length;
 300+ for (i = 0; i < length; i += 1) {
 301+ partial[i] = str(i, value) || 'null';
 302+ }
 303+
 304+// Join all of the elements together, separated with commas, and wrap them in
 305+// brackets.
 306+
 307+ v = partial.length === 0 ? '[]' : gap ?
 308+ '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
 309+ '[' + partial.join(',') + ']';
 310+ gap = mind;
 311+ return v;
 312+ }
 313+
 314+// If the replacer is an array, use it to select the members to be stringified.
 315+
 316+ if (rep && typeof rep === 'object') {
 317+ length = rep.length;
 318+ for (i = 0; i < length; i += 1) {
 319+ if (typeof rep[i] === 'string') {
 320+ k = rep[i];
 321+ v = str(k, value);
 322+ if (v) {
 323+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
 324+ }
 325+ }
 326+ }
 327+ } else {
 328+
 329+// Otherwise, iterate through all of the keys in the object.
 330+
 331+ for (k in value) {
 332+ if (Object.prototype.hasOwnProperty.call(value, k)) {
 333+ v = str(k, value);
 334+ if (v) {
 335+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
 336+ }
 337+ }
 338+ }
 339+ }
 340+
 341+// Join all of the member texts together, separated with commas,
 342+// and wrap them in braces.
 343+
 344+ v = partial.length === 0 ? '{}' : gap ?
 345+ '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
 346+ '{' + partial.join(',') + '}';
 347+ gap = mind;
 348+ return v;
 349+ }
 350+ }
 351+
 352+// If the JSON object does not yet have a stringify method, give it one.
 353+
 354+ if (typeof JSON.stringify !== 'function') {
 355+ JSON.stringify = function (value, replacer, space) {
 356+
 357+// The stringify method takes a value and an optional replacer, and an optional
 358+// space parameter, and returns a JSON text. The replacer can be a function
 359+// that can replace values, or an array of strings that will select the keys.
 360+// A default replacer method can be provided. Use of the space parameter can
 361+// produce text that is more easily readable.
 362+
 363+ var i;
 364+ gap = '';
 365+ indent = '';
 366+
 367+// If the space parameter is a number, make an indent string containing that
 368+// many spaces.
 369+
 370+ if (typeof space === 'number') {
 371+ for (i = 0; i < space; i += 1) {
 372+ indent += ' ';
 373+ }
 374+
 375+// If the space parameter is a string, it will be used as the indent string.
 376+
 377+ } else if (typeof space === 'string') {
 378+ indent = space;
 379+ }
 380+
 381+// If there is a replacer, it must be a function or an array.
 382+// Otherwise, throw an error.
 383+
 384+ rep = replacer;
 385+ if (replacer && typeof replacer !== 'function' &&
 386+ (typeof replacer !== 'object' ||
 387+ typeof replacer.length !== 'number')) {
 388+ throw new Error('JSON.stringify');
 389+ }
 390+
 391+// Make a fake root object containing our value under the key of ''.
 392+// Return the result of stringifying the value.
 393+
 394+ return str('', {'': value});
 395+ };
 396+ }
 397+
 398+
 399+// If the JSON object does not yet have a parse method, give it one.
 400+
 401+ if (typeof JSON.parse !== 'function') {
 402+ JSON.parse = function (text, reviver) {
 403+
 404+// The parse method takes a text and an optional reviver function, and returns
 405+// a JavaScript value if the text is a valid JSON text.
 406+
 407+ var j;
 408+
 409+ function walk(holder, key) {
 410+
 411+// The walk method is used to recursively walk the resulting structure so
 412+// that modifications can be made.
 413+
 414+ var k, v, value = holder[key];
 415+ if (value && typeof value === 'object') {
 416+ for (k in value) {
 417+ if (Object.prototype.hasOwnProperty.call(value, k)) {
 418+ v = walk(value, k);
 419+ if (v !== undefined) {
 420+ value[k] = v;
 421+ } else {
 422+ delete value[k];
 423+ }
 424+ }
 425+ }
 426+ }
 427+ return reviver.call(holder, key, value);
 428+ }
 429+
 430+
 431+// Parsing happens in four stages. In the first stage, we replace certain
 432+// Unicode characters with escape sequences. JavaScript handles many characters
 433+// incorrectly, either silently deleting them, or treating them as line endings.
 434+
 435+ text = String(text);
 436+ cx.lastIndex = 0;
 437+ if (cx.test(text)) {
 438+ text = text.replace(cx, function (a) {
 439+ return '\\u' +
 440+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 441+ });
 442+ }
 443+
 444+// In the second stage, we run the text against regular expressions that look
 445+// for non-JSON patterns. We are especially concerned with '()' and 'new'
 446+// because they can cause invocation, and '=' because it can cause mutation.
 447+// But just to be safe, we want to reject all unexpected forms.
 448+
 449+// We split the second stage into 4 regexp operations in order to work around
 450+// crippling inefficiencies in IE's and Safari's regexp engines. First we
 451+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
 452+// replace all simple value tokens with ']' characters. Third, we delete all
 453+// open brackets that follow a colon or comma or that begin the text. Finally,
 454+// we look to see that the remaining characters are only whitespace or ']' or
 455+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
 456+
 457+ if (/^[\],:{}\s]*$/
 458+ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
 459+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
 460+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
 461+
 462+// In the third stage we use the eval function to compile the text into a
 463+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
 464+// in JavaScript: it can begin a block or an object literal. We wrap the text
 465+// in parens to eliminate the ambiguity.
 466+
 467+ j = eval('(' + text + ')');
 468+
 469+// In the optional fourth stage, we recursively walk the new structure, passing
 470+// each name/value pair to a reviver function for possible transformation.
 471+
 472+ return typeof reviver === 'function' ?
 473+ walk({'': j}, '') : j;
 474+ }
 475+
 476+// If the text is not JSON parseable, then a SyntaxError is thrown.
 477+
 478+ throw new SyntaxError('JSON.parse');
 479+ };
 480+ }
 481+}());
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/JSON.js
___________________________________________________________________
Added: svn:eol-style
1482 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.special.surveys.js
@@ -0,0 +1,50 @@
 2+/**
 3+ * JavasSript for the Survey MediaWiki extension.
 4+ * @see https://secure.wikimedia.org/wikipedia/mediawiki/wiki/Extension:Survey
 5+ *
 6+ * @licence GNU GPL v3 or later
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+(function( $ ) { $( document ).ready( function() {
 11+
 12+ function deleteSurvey( options, successCallback, failCallback ) {
 13+ $.post(
 14+ wgScriptPath + '/api.php',
 15+ {
 16+ 'action': 'deletesurvey',
 17+ 'format': 'json',
 18+ 'ids': options.id,
 19+ 'token': options.token
 20+ },
 21+ function( data ) {
 22+ if ( data.success ) {
 23+ successCallback();
 24+ } else {
 25+ failCallback( mw.msg( 'surveys-special-delete-failed' ) );
 26+ }
 27+ }
 28+ );
 29+ }
 30+
 31+ $( '.survey-delete' ).click( function() {
 32+ $this = $( this );
 33+
 34+ if ( confirm( mw.msg( 'surveys-special-confirm-delete' ) ) ) {
 35+ deleteSurvey(
 36+ {
 37+ id: $this.attr( 'data-survey-id' ),
 38+ token: $this.attr( 'data-survey-token' )
 39+ },
 40+ function() {
 41+ $this.closest( 'tr' ).slideUp( 'slow', function() { $( this ).remove(); } );
 42+ },
 43+ function( error ) {
 44+ alert( error );
 45+ }
 46+ );
 47+ }
 48+ return false;
 49+ } );
 50+
 51+} ); })( jQuery );
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.special.surveys.js
___________________________________________________________________
Added: svn:eol-style
152 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.answerSelector.js
@@ -0,0 +1,55 @@
 2+/**
 3+ * JavasSript for the Survey MediaWiki extension.
 4+ * @see https://secure.wikimedia.org/wikipedia/mediawiki/wiki/Extension:Survey
 5+ *
 6+ * @licence GNU GPL v3 or later
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+(function( $, mw, survey ) {
 11+
 12+ survey.answerSelector = function( options ) {
 13+ var _this = this;
 14+
 15+ var defaults = {
 16+ 'visible': true,
 17+ 'answers': []
 18+ };
 19+
 20+ options = $.extend( defaults, options );
 21+
 22+ this.$div = $( '<div />' ).html( '' );
 23+
 24+ this.$div.append( $( '<p />' ).text( mw.msg( 'survey-special-label-answers' ) ) );
 25+
 26+ this.$div.append( $( '<textarea />' ).attr( options.attr ).val( options.answers.join( '\n' ) ) );
 27+
 28+ this.setVisible( options.visible );
 29+ };
 30+
 31+ survey.answerSelector.prototype = {
 32+
 33+ getHtml: function() {
 34+ return this.$div;
 35+ },
 36+
 37+ show: function() {
 38+ this.$div.show();
 39+ },
 40+
 41+ hide: function() {
 42+ this.$div.hide();
 43+ },
 44+
 45+ setVisible: function( visible ) {
 46+ if ( visible ) {
 47+ this.show();
 48+ }
 49+ else {
 50+ this.hide();
 51+ }
 52+ }
 53+
 54+ };
 55+
 56+} )( jQuery, window.mediaWiki, window.survey );
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.answerSelector.js
___________________________________________________________________
Added: svn:eol-style
157 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/jquery.survey.js
@@ -0,0 +1,313 @@
 2+/**
 3+ * JavasSript for the Survey MediaWiki extension.
 4+ * @see https://secure.wikimedia.org/wikipedia/mediawiki/wiki/Extension:Survey
 5+ *
 6+ * @licence GNU GPL v3 or later
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+( function ( $ ) { $.fn.mwSurvey = function( options ) {
 11+
 12+ var _this = this;
 13+ this.options = options;
 14+
 15+ this.inputs = [];
 16+
 17+ this.identifier = null;
 18+ this.identifierType = null;
 19+
 20+ this.getSurveyData = function( options, callback ) {
 21+ var requestArgs = {
 22+ 'action': 'query',
 23+ 'list': 'surveys',
 24+ 'format': 'json',
 25+ 'suincquestions': 1,
 26+ 'suprops': '*'
 27+ };
 28+
 29+ if ( options.requireEnabled ) {
 30+ requestArgs.suenabled = 1;
 31+ }
 32+
 33+ requestArgs[ 'su' + this.identifierType + 's' ] = this.identifier;
 34+
 35+ $.getJSON(
 36+ wgScriptPath + '/api.php',
 37+ requestArgs,
 38+ function( data ) {
 39+ if ( data.surveys ) {
 40+ callback( data.surveys );
 41+ } else if ( data.error ) {
 42+ debugger;
 43+ // TODO
 44+ } else {
 45+ debugger;
 46+ // TODO
 47+ }
 48+ }
 49+ );
 50+ };
 51+
 52+ this.getQuestionInput = function( question ) {
 53+ survey.log( 'getQuestionInput: ' + question.id );
 54+
 55+ var type = survey.question.type;
 56+
 57+ var $input;
 58+ var id = 'question-input-' + question.id;
 59+
 60+ switch ( question.type ) {
 61+ case type.TEXT: default:
 62+ $input = $( '<input />' ).attr( {
 63+ 'id': id,
 64+ 'class': 'question-input survey-text'
 65+ } );
 66+ break;
 67+ case type.NUMBER:
 68+ $input = $( '<input />' ).numeric().attr( {
 69+ 'id': id,
 70+ 'class': 'question-input survey-number',
 71+ 'size': 7
 72+ } );
 73+ break;
 74+ case type.SELECT:
 75+ var answers = {};
 76+
 77+ for ( i in question.answers ) {
 78+ answers[question.answers[i]] = question.answers[i];
 79+ }
 80+
 81+ $input = survey.htmlSelect( answers, 0, {
 82+ 'id': id,
 83+ 'class': 'question-input survey-select'
 84+ } );
 85+ break;
 86+ case type.RADIO:
 87+ var answers = {};
 88+
 89+ for ( i in question.answers ) {
 90+ answers[question.answers[i]] = question.answers[i];
 91+ }
 92+
 93+ $input = survey.htmlRadio(
 94+ answers,
 95+ null,
 96+ id,
 97+ {
 98+ 'id': id,
 99+ 'class': 'question-input survey-radio'
 100+ }
 101+ );
 102+ break;
 103+ case type.TEXTAREA:
 104+ $input = $( '<textarea />' ).attr( {
 105+ 'id': id,
 106+ 'class': 'question-input survey-textarea',
 107+ 'cols': 80,
 108+ 'rows': 2
 109+ } );
 110+ break;
 111+ case type.CHECK:
 112+ $input = $( '<input />' ).attr( {
 113+ 'id': id,
 114+ 'type': 'checkbox',
 115+ 'class': 'question-input survey-check'
 116+ } );
 117+ break;
 118+ }
 119+
 120+ $input.data( 'question-id', question.id );
 121+
 122+ this.inputs.push( { 'input': $input, 'type': question.type } );
 123+
 124+ $q = $( '<div />' ).attr( 'class', 'survey-question' ).html( $input );
 125+
 126+ if ( question.type === type.CHECK ) {
 127+ $q.prepend( $( '<label />' ).text( question.text ).attr( 'for', id ) );
 128+ }
 129+ else {
 130+ $q.prepend( $( '<p />' ).text( question.text ).attr( 'class', 'question-text' ) );
 131+ }
 132+
 133+ return $q;
 134+ };
 135+
 136+ this.getSurveyQuestion = function( question ) {
 137+ if ( survey.question.typeHasAnswers( question.type )
 138+ && question.answers.length == 0 ) {
 139+ survey.log( 'getSurveyQuestion: no answers for: ' + question.id );
 140+ return '';
 141+ }
 142+ else {
 143+ return this.getQuestionInput( question );
 144+ }
 145+ };
 146+
 147+ this.getSurveyQuestions = function( questions ) {
 148+ $questions = $( '<div />' );
 149+
 150+ for ( i in questions ) {
 151+ $questions.append( this.getSurveyQuestion( questions[i] ) );
 152+ }
 153+
 154+ return $questions;
 155+ };
 156+
 157+ this.getAnswers = function( surveyId ) {
 158+ var answers = [];
 159+
 160+ for ( i in this.inputs ) {
 161+ var $input = this.inputs[i].input;
 162+ var id = $input.data( 'question-id' );
 163+
 164+ if ( this.inputs[i].type === survey.question.type.RADIO ) {
 165+ var value = $( 'input:radio[name=question-input-' + id + ']:checked' ).val();
 166+ }
 167+ else {
 168+ var value = $input.val();
 169+ }
 170+
 171+ answers.push( {
 172+ 'text': value,
 173+ 'question_id': id
 174+ } );
 175+ }
 176+
 177+ return JSON.stringify( answers );
 178+ };
 179+
 180+ this.submitSurvey = function( surveyId, callback ) {
 181+ var requestArgs = {
 182+ 'action': 'submitsurvey',
 183+ 'format': 'json',
 184+ 'token': $( this ).attr( 'survey-data-token' ),
 185+ 'answers': this.getAnswers( surveyId )
 186+ };
 187+
 188+ requestArgs[this.identifierType] = this.identifier;
 189+
 190+ $.post(
 191+ wgScriptPath + '/api.php',
 192+ requestArgs,
 193+ function( data ) {
 194+ callback();
 195+ // TODO
 196+ }
 197+ );
 198+ };
 199+
 200+ this.doCompletion = function() {
 201+ $.fancybox.close();
 202+ };
 203+
 204+ this.showCompletion = function( surveyData ) {
 205+ $div = $( '#survey-' + surveyData.id );
 206+
 207+ $div.html( $( '<p />' ).text( surveyData.thanks ) );
 208+
 209+ $div.append( $( '<button />' )
 210+ .button( { label: mw.msg( 'survey-jquery-finish' ) } )
 211+ .click( this.doCompletion )
 212+ );
 213+ };
 214+
 215+ this.getSurveyBody = function( surveyData ) {
 216+ $survey = $( '<div />' );
 217+
 218+ $survey.append( $( '<h1 />' ).text( surveyData.title ) );
 219+
 220+ $survey.append( $( '<p />' ).text( surveyData.header ) );
 221+
 222+ $survey.append( this.getSurveyQuestions( surveyData.questions ) );
 223+
 224+ var submissionButton = $( '<button />' )
 225+ .button( { label: mw.msg( 'survey-jquery-submit' ) } )
 226+ .click( function() {
 227+ var $this = $( this );
 228+ $this.button( 'disable' );
 229+
 230+ if ( true /* isValid */ ) {
 231+ _this.submitSurvey(
 232+ surveyData.id,
 233+ function() {
 234+ if ( surveyData.thanks == '' ) {
 235+ _this.doCompletion();
 236+ } else {
 237+ _this.showCompletion( surveyData );
 238+ }
 239+ }
 240+ );
 241+ } else {
 242+ // TODO
 243+
 244+ $this.button( 'enable' );
 245+ }
 246+ } );
 247+
 248+ $survey.append( submissionButton );
 249+
 250+ $survey.append( $( '<p />' ).text( surveyData.footer ) );
 251+
 252+ return $survey;
 253+ };
 254+
 255+ this.initSurvey = function( surveyData ) {
 256+ $div = $( '<div />' ).attr( {
 257+ 'style': 'display:none'
 258+ } ).html( $( '<div />' ).attr( { 'id': 'survey-' + surveyData.id } ).html( this.getSurveyBody( surveyData ) ) );
 259+
 260+ $link = $( '<a />' ).attr( {
 261+ 'href': '#survey-' + surveyData.id
 262+ } ).html( $div );
 263+
 264+ $( this ).html( $link );
 265+
 266+ $link.fancybox( {
 267+// 'width' : '75%',
 268+// 'height' : '75%',
 269+ 'autoScale' : false,
 270+ 'transitionIn' : 'none',
 271+ 'transitionOut' : 'none',
 272+ 'type' : 'inline',
 273+ 'hideOnOverlayClick': false,
 274+ 'autoDimensions': true
 275+ } );
 276+
 277+ $link.click();
 278+
 279+ if ( typeof this.options.onShow === 'function' ) {
 280+ this.options.onShow( { 'id': surveyData.id } );
 281+ }
 282+ };
 283+
 284+ this.init = function() {
 285+ var $this = $( this );
 286+
 287+ if ( $this.attr( 'survey-data-id' ) ) {
 288+ this.identifier = $this.attr( 'survey-data-id' );
 289+ this.identifierType = 'id';
 290+ } else if ( $this.attr( 'survey-data-name' ) ) {
 291+ this.identifier = $this.attr( 'survey-data-name' );
 292+ this.identifierType = 'name';
 293+ }
 294+
 295+ if ( this.identifier !== null ) {
 296+ this.getSurveyData(
 297+ {
 298+ 'requireEnabled': $this.attr( 'survey-data-require-enabled' ) !== '0'
 299+ },
 300+ function( surveyData ) {
 301+ if ( surveyData.hasOwnProperty( 0 ) ) {
 302+ _this.initSurvey( surveyData[0] );
 303+ }
 304+ else {
 305+ $this.text( mw.msg( 'survey-jquery-load-failed' ) );
 306+ }
 307+ }
 308+ );
 309+ }
 310+ };
 311+
 312+ this.init();
 313+
 314+}; } )( jQuery );
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/jquery.survey.js
___________________________________________________________________
Added: svn:eol-style
1315 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.js
@@ -0,0 +1,126 @@
 2+/**
 3+ * JavasSript for the Survey MediaWiki extension.
 4+ * @see https://secure.wikimedia.org/wikipedia/mediawiki/wiki/Extension:Survey
 5+ *
 6+ * @licence GNU GPL v3 or later
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+window.survey = new( function() {
 11+
 12+ this.log = function( message ) {
 13+ if ( mediaWiki.config.get( 'wgSurveyDebug' ) ) {
 14+ if ( typeof mediaWiki === 'undefined' ) {
 15+ if ( typeof console !== 'undefined' ) {
 16+ console.log( 'Survey: ' + message );
 17+ }
 18+ } else {
 19+ return mediaWiki.log.call( mediaWiki.log, 'Survey: ' + message );
 20+ }
 21+ }
 22+ };
 23+
 24+ this.msg = function() {
 25+ if ( typeof mediaWiki === 'undefined' ) {
 26+ message = window.wgSurveyMessages[arguments[0]];
 27+
 28+ for ( var i = arguments.length - 1; i > 0; i-- ) {
 29+ message = message.replace( '$' + i, arguments[i] );
 30+ }
 31+
 32+ return message;
 33+ } else {
 34+ return mediaWiki.msg.apply( mediaWiki.msg, arguments );
 35+ }
 36+ };
 37+
 38+ this.htmlSelect = function( options, value, attributes, onChangeCallback ) {
 39+ $select = $( '<select />' ).attr( attributes );
 40+
 41+ for ( message in options ) {
 42+ var attribs = { 'value': options[message] };
 43+
 44+ if ( value === options[message] ) {
 45+ attribs.selected = 'selected';
 46+ }
 47+
 48+ $select.append( $( '<option />' ).text( message ).attr( attribs ) );
 49+ }
 50+
 51+ if ( typeof onChangeCallback !== 'undefined' ) {
 52+ $select.change( function() { onChangeCallback( $( this ).val() ) } );
 53+ }
 54+
 55+ return $select;
 56+ };
 57+
 58+ this.htmlRadio = function( options, value, name, attributes ) {
 59+ var $radio = $( '<div />' ).attr( attributes );
 60+ $radio.html( '' );
 61+
 62+ for ( message in options ) {
 63+ var itemValue = options[message];
 64+ var id = name + itemValue;
 65+
 66+// if ( value === null ) {
 67+// value = itemValue;
 68+// }
 69+
 70+ $input = $( '<input />' ).attr( {
 71+ 'id': id,
 72+ 'type': 'radio',
 73+ 'name': name,
 74+ 'value': itemValue
 75+ } );
 76+
 77+ if ( value === options[message] ) {
 78+ $input.attr( 'checked', 'checked' );
 79+ }
 80+
 81+ $radio.append( $input );
 82+ $radio.append( $( '<label />' ).attr( 'for', id ).text( message ) );
 83+ $radio.append( $( '<br />' ) );
 84+ }
 85+
 86+ return $radio;
 87+ };
 88+
 89+ this.question = new( function() {
 90+
 91+ this.type = new( function() {
 92+ this.TEXT = 0;
 93+ this.NUMBER = 1;
 94+ this.SELECT = 2;
 95+ this.RADIO = 3;
 96+ this.TEXTAREA = 4;
 97+ this.CHECK = 5;
 98+ } );
 99+
 100+ this.typeHasAnswers = function( t ) {
 101+ return $.inArray( t, [ survey.question.type.RADIO, survey.question.type.SELECT ] ) !== -1;
 102+ };
 103+
 104+ this.getTypeSelector = function( value, attributes, onChangeCallback ) {
 105+ var options = [];
 106+
 107+ var types = {
 108+ 'text': survey.question.type.TEXT,
 109+ 'number': survey.question.type.NUMBER,
 110+ 'select': survey.question.type.SELECT,
 111+ 'radio': survey.question.type.RADIO,
 112+ 'textarea': survey.question.type.TEXTAREA,
 113+ 'check': survey.question.type.CHECK
 114+ };
 115+
 116+ for ( msg in types ) {
 117+ options[survey.msg( 'survey-question-type-' + msg )] = types[msg];
 118+ }
 119+
 120+ return survey.htmlSelect( options, parseInt( value ), attributes, onChangeCallback );
 121+ };
 122+
 123+ } );
 124+
 125+} )();
 126+
 127+
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.js
___________________________________________________________________
Added: svn:eol-style
1128 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.fancybox-1.3.4.css
@@ -0,0 +1,359 @@
 2+/*
 3+ * FancyBox - jQuery Plugin
 4+ * Simple and fancy lightbox alternative
 5+ *
 6+ * Examples and documentation at: http://fancybox.net
 7+ *
 8+ * Copyright (c) 2008 - 2010 Janis Skarnelis
 9+ * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
 10+ *
 11+ * Version: 1.3.4 (11/11/2010)
 12+ * Requires: jQuery v1.3+
 13+ *
 14+ * Dual licensed under the MIT and GPL licenses:
 15+ * http://www.opensource.org/licenses/mit-license.php
 16+ * http://www.gnu.org/licenses/gpl.html
 17+ */
 18+
 19+#fancybox-loading {
 20+ position: fixed;
 21+ top: 50%;
 22+ left: 50%;
 23+ width: 40px;
 24+ height: 40px;
 25+ margin-top: -20px;
 26+ margin-left: -20px;
 27+ cursor: pointer;
 28+ overflow: hidden;
 29+ z-index: 1104;
 30+ display: none;
 31+}
 32+
 33+#fancybox-loading div {
 34+ position: absolute;
 35+ top: 0;
 36+ left: 0;
 37+ width: 40px;
 38+ height: 480px;
 39+ background-image: url('fancybox.png');
 40+}
 41+
 42+#fancybox-overlay {
 43+ position: absolute;
 44+ top: 0;
 45+ left: 0;
 46+ width: 100%;
 47+ z-index: 1100;
 48+ display: none;
 49+}
 50+
 51+#fancybox-tmp {
 52+ padding: 0;
 53+ margin: 0;
 54+ border: 0;
 55+ overflow: auto;
 56+ display: none;
 57+}
 58+
 59+#fancybox-wrap {
 60+ position: absolute;
 61+ top: 0;
 62+ left: 0;
 63+ padding: 20px;
 64+ z-index: 1101;
 65+ outline: none;
 66+ display: none;
 67+}
 68+
 69+#fancybox-outer {
 70+ position: relative;
 71+ width: 100%;
 72+ height: 100%;
 73+ background: #fff;
 74+}
 75+
 76+#fancybox-content {
 77+ width: 0;
 78+ height: 0;
 79+ padding: 0;
 80+ outline: none;
 81+ position: relative;
 82+ overflow: hidden;
 83+ z-index: 1102;
 84+ border: 0px solid #fff;
 85+}
 86+
 87+#fancybox-hide-sel-frame {
 88+ position: absolute;
 89+ top: 0;
 90+ left: 0;
 91+ width: 100%;
 92+ height: 100%;
 93+ background: transparent;
 94+ z-index: 1101;
 95+}
 96+
 97+#fancybox-close {
 98+ position: absolute;
 99+ top: -15px;
 100+ right: -15px;
 101+ width: 30px;
 102+ height: 30px;
 103+ background: transparent url('fancybox.png') -40px 0px;
 104+ cursor: pointer;
 105+ z-index: 1103;
 106+ display: none;
 107+}
 108+
 109+#fancybox-error {
 110+ color: #444;
 111+ font: normal 12px/20px Arial;
 112+ padding: 14px;
 113+ margin: 0;
 114+}
 115+
 116+#fancybox-img {
 117+ width: 100%;
 118+ height: 100%;
 119+ padding: 0;
 120+ margin: 0;
 121+ border: none;
 122+ outline: none;
 123+ line-height: 0;
 124+ vertical-align: top;
 125+}
 126+
 127+#fancybox-frame {
 128+ width: 100%;
 129+ height: 100%;
 130+ border: none;
 131+ display: block;
 132+}
 133+
 134+#fancybox-left, #fancybox-right {
 135+ position: absolute;
 136+ bottom: 0px;
 137+ height: 100%;
 138+ width: 35%;
 139+ cursor: pointer;
 140+ outline: none;
 141+ background: transparent url('blank.gif');
 142+ z-index: 1102;
 143+ display: none;
 144+}
 145+
 146+#fancybox-left {
 147+ left: 0px;
 148+}
 149+
 150+#fancybox-right {
 151+ right: 0px;
 152+}
 153+
 154+#fancybox-left-ico, #fancybox-right-ico {
 155+ position: absolute;
 156+ top: 50%;
 157+ left: -9999px;
 158+ width: 30px;
 159+ height: 30px;
 160+ margin-top: -15px;
 161+ cursor: pointer;
 162+ z-index: 1102;
 163+ display: block;
 164+}
 165+
 166+#fancybox-left-ico {
 167+ background-image: url('fancybox.png');
 168+ background-position: -40px -30px;
 169+}
 170+
 171+#fancybox-right-ico {
 172+ background-image: url('fancybox.png');
 173+ background-position: -40px -60px;
 174+}
 175+
 176+#fancybox-left:hover, #fancybox-right:hover {
 177+ visibility: visible; /* IE6 */
 178+}
 179+
 180+#fancybox-left:hover span {
 181+ left: 20px;
 182+}
 183+
 184+#fancybox-right:hover span {
 185+ left: auto;
 186+ right: 20px;
 187+}
 188+
 189+.fancybox-bg {
 190+ position: absolute;
 191+ padding: 0;
 192+ margin: 0;
 193+ border: 0;
 194+ width: 20px;
 195+ height: 20px;
 196+ z-index: 1001;
 197+}
 198+
 199+#fancybox-bg-n {
 200+ top: -20px;
 201+ left: 0;
 202+ width: 100%;
 203+ background-image: url('fancybox-x.png');
 204+}
 205+
 206+#fancybox-bg-ne {
 207+ top: -20px;
 208+ right: -20px;
 209+ background-image: url('fancybox.png');
 210+ background-position: -40px -162px;
 211+}
 212+
 213+#fancybox-bg-e {
 214+ top: 0;
 215+ right: -20px;
 216+ height: 100%;
 217+ background-image: url('fancybox-y.png');
 218+ background-position: -20px 0px;
 219+}
 220+
 221+#fancybox-bg-se {
 222+ bottom: -20px;
 223+ right: -20px;
 224+ background-image: url('fancybox.png');
 225+ background-position: -40px -182px;
 226+}
 227+
 228+#fancybox-bg-s {
 229+ bottom: -20px;
 230+ left: 0;
 231+ width: 100%;
 232+ background-image: url('fancybox-x.png');
 233+ background-position: 0px -20px;
 234+}
 235+
 236+#fancybox-bg-sw {
 237+ bottom: -20px;
 238+ left: -20px;
 239+ background-image: url('fancybox.png');
 240+ background-position: -40px -142px;
 241+}
 242+
 243+#fancybox-bg-w {
 244+ top: 0;
 245+ left: -20px;
 246+ height: 100%;
 247+ background-image: url('fancybox-y.png');
 248+}
 249+
 250+#fancybox-bg-nw {
 251+ top: -20px;
 252+ left: -20px;
 253+ background-image: url('fancybox.png');
 254+ background-position: -40px -122px;
 255+}
 256+
 257+#fancybox-title {
 258+ font-family: Helvetica;
 259+ font-size: 12px;
 260+ z-index: 1102;
 261+}
 262+
 263+.fancybox-title-inside {
 264+ padding-bottom: 10px;
 265+ text-align: center;
 266+ color: #333;
 267+ background: #fff;
 268+ position: relative;
 269+}
 270+
 271+.fancybox-title-outside {
 272+ padding-top: 10px;
 273+ color: #fff;
 274+}
 275+
 276+.fancybox-title-over {
 277+ position: absolute;
 278+ bottom: 0;
 279+ left: 0;
 280+ color: #FFF;
 281+ text-align: left;
 282+}
 283+
 284+#fancybox-title-over {
 285+ padding: 10px;
 286+ background-image: url('fancy_title_over.png');
 287+ display: block;
 288+}
 289+
 290+.fancybox-title-float {
 291+ position: absolute;
 292+ left: 0;
 293+ bottom: -20px;
 294+ height: 32px;
 295+}
 296+
 297+#fancybox-title-float-wrap {
 298+ border: none;
 299+ border-collapse: collapse;
 300+ width: auto;
 301+}
 302+
 303+#fancybox-title-float-wrap td {
 304+ border: none;
 305+ white-space: nowrap;
 306+}
 307+
 308+#fancybox-title-float-left {
 309+ padding: 0 0 0 15px;
 310+ background: url('fancybox.png') -40px -90px no-repeat;
 311+}
 312+
 313+#fancybox-title-float-main {
 314+ color: #FFF;
 315+ line-height: 29px;
 316+ font-weight: bold;
 317+ padding: 0 0 3px 0;
 318+ background: url('fancybox-x.png') 0px -40px;
 319+}
 320+
 321+#fancybox-title-float-right {
 322+ padding: 0 0 0 15px;
 323+ background: url('fancybox.png') -55px -90px no-repeat;
 324+}
 325+
 326+/* IE6 */
 327+
 328+.fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); }
 329+
 330+.fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); }
 331+.fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); }
 332+
 333+.fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
 334+.fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); }
 335+.fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); }
 336+.fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); }
 337+
 338+.fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame {
 339+ height: expression(this.parentNode.clientHeight + "px");
 340+}
 341+
 342+#fancybox-loading.fancybox-ie6 {
 343+ position: absolute; margin-top: 0;
 344+ top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px');
 345+}
 346+
 347+#fancybox-loading.fancybox-ie6 div { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); }
 348+
 349+/* IE6, IE7, IE8 */
 350+
 351+.fancybox-ie .fancybox-bg { background: transparent !important; }
 352+
 353+.fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); }
 354+.fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); }
 355+.fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); }
 356+.fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); }
 357+.fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); }
 358+.fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); }
 359+.fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); }
 360+.fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.fancybox-1.3.4.css
___________________________________________________________________
Added: svn:eol-style
1361 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_se.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_se.png
___________________________________________________________________
Added: svn:mime-type
2362 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_title_over.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_title_over.png
___________________________________________________________________
Added: svn:mime-type
3363 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.fancybox-1.3.4.pack.js
@@ -0,0 +1,46 @@
 2+/*
 3+ * FancyBox - jQuery Plugin
 4+ * Simple and fancy lightbox alternative
 5+ *
 6+ * Examples and documentation at: http://fancybox.net
 7+ *
 8+ * Copyright (c) 2008 - 2010 Janis Skarnelis
 9+ * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
 10+ *
 11+ * Version: 1.3.4 (11/11/2010)
 12+ * Requires: jQuery v1.3+
 13+ *
 14+ * Dual licensed under the MIT and GPL licenses:
 15+ * http://www.opensource.org/licenses/mit-license.php
 16+ * http://www.gnu.org/licenses/gpl.html
 17+ */
 18+
 19+;(function(b){var m,t,u,f,D,j,E,n,z,A,q=0,e={},o=[],p=0,d={},l=[],G=null,v=new Image,J=/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,W=/[^\.]\.(swf)\s*$/i,K,L=1,y=0,s="",r,i,h=false,B=b.extend(b("<div/>")[0],{prop:0}),M=b.browser.msie&&b.browser.version<7&&!window.XMLHttpRequest,N=function(){t.hide();v.onerror=v.onload=null;G&&G.abort();m.empty()},O=function(){if(false===e.onError(o,q,e)){t.hide();h=false}else{e.titleShow=false;e.width="auto";e.height="auto";m.html('<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>');
 20+F()}},I=function(){var a=o[q],c,g,k,C,P,w;N();e=b.extend({},b.fn.fancybox.defaults,typeof b(a).data("fancybox")=="undefined"?e:b(a).data("fancybox"));w=e.onStart(o,q,e);if(w===false)h=false;else{if(typeof w=="object")e=b.extend(e,w);k=e.title||(a.nodeName?b(a).attr("title"):a.title)||"";if(a.nodeName&&!e.orig)e.orig=b(a).children("img:first").length?b(a).children("img:first"):b(a);if(k===""&&e.orig&&e.titleFromAlt)k=e.orig.attr("alt");c=e.href||(a.nodeName?b(a).attr("href"):a.href)||null;if(/^(?:javascript)/i.test(c)||
 21+c=="#")c=null;if(e.type){g=e.type;if(!c)c=e.content}else if(e.content)g="html";else if(c)g=c.match(J)?"image":c.match(W)?"swf":b(a).hasClass("iframe")?"iframe":c.indexOf("#")===0?"inline":"ajax";if(g){if(g=="inline"){a=c.substr(c.indexOf("#"));g=b(a).length>0?"inline":"ajax"}e.type=g;e.href=c;e.title=k;if(e.autoDimensions)if(e.type=="html"||e.type=="inline"||e.type=="ajax"){e.width="auto";e.height="auto"}else e.autoDimensions=false;if(e.modal){e.overlayShow=true;e.hideOnOverlayClick=false;e.hideOnContentClick=
 22+false;e.enableEscapeButton=false;e.showCloseButton=false}e.padding=parseInt(e.padding,10);e.margin=parseInt(e.margin,10);m.css("padding",e.padding+e.margin);b(".fancybox-inline-tmp").unbind("fancybox-cancel").bind("fancybox-change",function(){b(this).replaceWith(j.children())});switch(g){case "html":m.html(e.content);F();break;case "inline":if(b(a).parent().is("#fancybox-content")===true){h=false;break}b('<div class="fancybox-inline-tmp" />').hide().insertBefore(b(a)).bind("fancybox-cleanup",function(){b(this).replaceWith(j.children())}).bind("fancybox-cancel",
 23+function(){b(this).replaceWith(m.children())});b(a).appendTo(m);F();break;case "image":h=false;b.fancybox.showActivity();v=new Image;v.onerror=function(){O()};v.onload=function(){h=true;v.onerror=v.onload=null;e.width=v.width;e.height=v.height;b("<img />").attr({id:"fancybox-img",src:v.src,alt:e.title}).appendTo(m);Q()};v.src=c;break;case "swf":e.scrolling="no";C='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+e.width+'" height="'+e.height+'"><param name="movie" value="'+c+
 24+'"></param>';P="";b.each(e.swf,function(x,H){C+='<param name="'+x+'" value="'+H+'"></param>';P+=" "+x+'="'+H+'"'});C+='<embed src="'+c+'" type="application/x-shockwave-flash" width="'+e.width+'" height="'+e.height+'"'+P+"></embed></object>";m.html(C);F();break;case "ajax":h=false;b.fancybox.showActivity();e.ajax.win=e.ajax.success;G=b.ajax(b.extend({},e.ajax,{url:c,data:e.ajax.data||{},error:function(x){x.status>0&&O()},success:function(x,H,R){if((typeof R=="object"?R:G).status==200){if(typeof e.ajax.win==
 25+"function"){w=e.ajax.win(c,x,H,R);if(w===false){t.hide();return}else if(typeof w=="string"||typeof w=="object")x=w}m.html(x);F()}}}));break;case "iframe":Q()}}else O()}},F=function(){var a=e.width,c=e.height;a=a.toString().indexOf("%")>-1?parseInt((b(window).width()-e.margin*2)*parseFloat(a)/100,10)+"px":a=="auto"?"auto":a+"px";c=c.toString().indexOf("%")>-1?parseInt((b(window).height()-e.margin*2)*parseFloat(c)/100,10)+"px":c=="auto"?"auto":c+"px";m.wrapInner('<div style="width:'+a+";height:"+c+
 26+";overflow: "+(e.scrolling=="auto"?"auto":e.scrolling=="yes"?"scroll":"hidden")+';position:relative;"></div>');e.width=m.width();e.height=m.height();Q()},Q=function(){var a,c;t.hide();if(f.is(":visible")&&false===d.onCleanup(l,p,d)){b.event.trigger("fancybox-cancel");h=false}else{h=true;b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");f.is(":visible")&&d.titlePosition!=="outside"&&f.css("height",f.height());l=o;p=q;d=e;if(d.overlayShow){u.css({"background-color":d.overlayColor,
 27+opacity:d.overlayOpacity,cursor:d.hideOnOverlayClick?"pointer":"auto",height:b(document).height()});if(!u.is(":visible")){M&&b("select:not(#fancybox-tmp select)").filter(function(){return this.style.visibility!=="hidden"}).css({visibility:"hidden"}).one("fancybox-cleanup",function(){this.style.visibility="inherit"});u.show()}}else u.hide();i=X();s=d.title||"";y=0;n.empty().removeAttr("style").removeClass();if(d.titleShow!==false){if(b.isFunction(d.titleFormat))a=d.titleFormat(s,l,p,d);else a=s&&s.length?
 28+d.titlePosition=="float"?'<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">'+s+'</td><td id="fancybox-title-float-right"></td></tr></table>':'<div id="fancybox-title-'+d.titlePosition+'">'+s+"</div>":false;s=a;if(!(!s||s==="")){n.addClass("fancybox-title-"+d.titlePosition).html(s).appendTo("body").show();switch(d.titlePosition){case "inside":n.css({width:i.width-d.padding*2,marginLeft:d.padding,marginRight:d.padding});
 29+y=n.outerHeight(true);n.appendTo(D);i.height+=y;break;case "over":n.css({marginLeft:d.padding,width:i.width-d.padding*2,bottom:d.padding}).appendTo(D);break;case "float":n.css("left",parseInt((n.width()-i.width-40)/2,10)*-1).appendTo(f);break;default:n.css({width:i.width-d.padding*2,paddingLeft:d.padding,paddingRight:d.padding}).appendTo(f)}}}n.hide();if(f.is(":visible")){b(E.add(z).add(A)).hide();a=f.position();r={top:a.top,left:a.left,width:f.width(),height:f.height()};c=r.width==i.width&&r.height==
 30+i.height;j.fadeTo(d.changeFade,0.3,function(){var g=function(){j.html(m.contents()).fadeTo(d.changeFade,1,S)};b.event.trigger("fancybox-change");j.empty().removeAttr("filter").css({"border-width":d.padding,width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2});if(c)g();else{B.prop=0;b(B).animate({prop:1},{duration:d.changeSpeed,easing:d.easingChange,step:T,complete:g})}})}else{f.removeAttr("style");j.css("border-width",d.padding);if(d.transitionIn=="elastic"){r=V();j.html(m.contents());
 31+f.show();if(d.opacity)i.opacity=0;B.prop=0;b(B).animate({prop:1},{duration:d.speedIn,easing:d.easingIn,step:T,complete:S})}else{d.titlePosition=="inside"&&y>0&&n.show();j.css({width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2}).html(m.contents());f.css(i).fadeIn(d.transitionIn=="none"?0:d.speedIn,S)}}}},Y=function(){if(d.enableEscapeButton||d.enableKeyboardNav)b(document).bind("keydown.fb",function(a){if(a.keyCode==27&&d.enableEscapeButton){a.preventDefault();b.fancybox.close()}else if((a.keyCode==
 32+37||a.keyCode==39)&&d.enableKeyboardNav&&a.target.tagName!=="INPUT"&&a.target.tagName!=="TEXTAREA"&&a.target.tagName!=="SELECT"){a.preventDefault();b.fancybox[a.keyCode==37?"prev":"next"]()}});if(d.showNavArrows){if(d.cyclic&&l.length>1||p!==0)z.show();if(d.cyclic&&l.length>1||p!=l.length-1)A.show()}else{z.hide();A.hide()}},S=function(){if(!b.support.opacity){j.get(0).style.removeAttribute("filter");f.get(0).style.removeAttribute("filter")}e.autoDimensions&&j.css("height","auto");f.css("height","auto");
 33+s&&s.length&&n.show();d.showCloseButton&&E.show();Y();d.hideOnContentClick&&j.bind("click",b.fancybox.close);d.hideOnOverlayClick&&u.bind("click",b.fancybox.close);b(window).bind("resize.fb",b.fancybox.resize);d.centerOnScroll&&b(window).bind("scroll.fb",b.fancybox.center);if(d.type=="iframe")b('<iframe id="fancybox-frame" name="fancybox-frame'+(new Date).getTime()+'" frameborder="0" hspace="0" '+(b.browser.msie?'allowtransparency="true""':"")+' scrolling="'+e.scrolling+'" src="'+d.href+'"></iframe>').appendTo(j);
 34+f.show();h=false;b.fancybox.center();d.onComplete(l,p,d);var a,c;if(l.length-1>p){a=l[p+1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}if(p>0){a=l[p-1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}},T=function(a){var c={width:parseInt(r.width+(i.width-r.width)*a,10),height:parseInt(r.height+(i.height-r.height)*a,10),top:parseInt(r.top+(i.top-r.top)*a,10),left:parseInt(r.left+(i.left-r.left)*a,10)};if(typeof i.opacity!=="undefined")c.opacity=a<0.5?0.5:a;f.css(c);
 35+j.css({width:c.width-d.padding*2,height:c.height-y*a-d.padding*2})},U=function(){return[b(window).width()-d.margin*2,b(window).height()-d.margin*2,b(document).scrollLeft()+d.margin,b(document).scrollTop()+d.margin]},X=function(){var a=U(),c={},g=d.autoScale,k=d.padding*2;c.width=d.width.toString().indexOf("%")>-1?parseInt(a[0]*parseFloat(d.width)/100,10):d.width+k;c.height=d.height.toString().indexOf("%")>-1?parseInt(a[1]*parseFloat(d.height)/100,10):d.height+k;if(g&&(c.width>a[0]||c.height>a[1]))if(e.type==
 36+"image"||e.type=="swf"){g=d.width/d.height;if(c.width>a[0]){c.width=a[0];c.height=parseInt((c.width-k)/g+k,10)}if(c.height>a[1]){c.height=a[1];c.width=parseInt((c.height-k)*g+k,10)}}else{c.width=Math.min(c.width,a[0]);c.height=Math.min(c.height,a[1])}c.top=parseInt(Math.max(a[3]-20,a[3]+(a[1]-c.height-40)*0.5),10);c.left=parseInt(Math.max(a[2]-20,a[2]+(a[0]-c.width-40)*0.5),10);return c},V=function(){var a=e.orig?b(e.orig):false,c={};if(a&&a.length){c=a.offset();c.top+=parseInt(a.css("paddingTop"),
 37+10)||0;c.left+=parseInt(a.css("paddingLeft"),10)||0;c.top+=parseInt(a.css("border-top-width"),10)||0;c.left+=parseInt(a.css("border-left-width"),10)||0;c.width=a.width();c.height=a.height();c={width:c.width+d.padding*2,height:c.height+d.padding*2,top:c.top-d.padding-20,left:c.left-d.padding-20}}else{a=U();c={width:d.padding*2,height:d.padding*2,top:parseInt(a[3]+a[1]*0.5,10),left:parseInt(a[2]+a[0]*0.5,10)}}return c},Z=function(){if(t.is(":visible")){b("div",t).css("top",L*-40+"px");L=(L+1)%12}else clearInterval(K)};
 38+b.fn.fancybox=function(a){if(!b(this).length)return this;b(this).data("fancybox",b.extend({},a,b.metadata?b(this).metadata():{})).unbind("click.fb").bind("click.fb",function(c){c.preventDefault();if(!h){h=true;b(this).blur();o=[];q=0;c=b(this).attr("rel")||"";if(!c||c==""||c==="nofollow")o.push(this);else{o=b("a[rel="+c+"], area[rel="+c+"]");q=o.index(this)}I()}});return this};b.fancybox=function(a,c){var g;if(!h){h=true;g=typeof c!=="undefined"?c:{};o=[];q=parseInt(g.index,10)||0;if(b.isArray(a)){for(var k=
 39+0,C=a.length;k<C;k++)if(typeof a[k]=="object")b(a[k]).data("fancybox",b.extend({},g,a[k]));else a[k]=b({}).data("fancybox",b.extend({content:a[k]},g));o=jQuery.merge(o,a)}else{if(typeof a=="object")b(a).data("fancybox",b.extend({},g,a));else a=b({}).data("fancybox",b.extend({content:a},g));o.push(a)}if(q>o.length||q<0)q=0;I()}};b.fancybox.showActivity=function(){clearInterval(K);t.show();K=setInterval(Z,66)};b.fancybox.hideActivity=function(){t.hide()};b.fancybox.next=function(){return b.fancybox.pos(p+
 40+1)};b.fancybox.prev=function(){return b.fancybox.pos(p-1)};b.fancybox.pos=function(a){if(!h){a=parseInt(a);o=l;if(a>-1&&a<l.length){q=a;I()}else if(d.cyclic&&l.length>1){q=a>=l.length?0:l.length-1;I()}}};b.fancybox.cancel=function(){if(!h){h=true;b.event.trigger("fancybox-cancel");N();e.onCancel(o,q,e);h=false}};b.fancybox.close=function(){function a(){u.fadeOut("fast");n.empty().hide();f.hide();b.event.trigger("fancybox-cleanup");j.empty();d.onClosed(l,p,d);l=e=[];p=q=0;d=e={};h=false}if(!(h||f.is(":hidden"))){h=
 41+true;if(d&&false===d.onCleanup(l,p,d))h=false;else{N();b(E.add(z).add(A)).hide();b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");j.find("iframe").attr("src",M&&/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank");d.titlePosition!=="inside"&&n.empty();f.stop();if(d.transitionOut=="elastic"){r=V();var c=f.position();i={top:c.top,left:c.left,width:f.width(),height:f.height()};if(d.opacity)i.opacity=1;n.empty().hide();B.prop=1;
 42+b(B).animate({prop:0},{duration:d.speedOut,easing:d.easingOut,step:T,complete:a})}else f.fadeOut(d.transitionOut=="none"?0:d.speedOut,a)}}};b.fancybox.resize=function(){u.is(":visible")&&u.css("height",b(document).height());b.fancybox.center(true)};b.fancybox.center=function(a){var c,g;if(!h){g=a===true?1:0;c=U();!g&&(f.width()>c[0]||f.height()>c[1])||f.stop().animate({top:parseInt(Math.max(c[3]-20,c[3]+(c[1]-j.height()-40)*0.5-d.padding)),left:parseInt(Math.max(c[2]-20,c[2]+(c[0]-j.width()-40)*0.5-
 43+d.padding))},typeof a=="number"?a:200)}};b.fancybox.init=function(){if(!b("#fancybox-wrap").length){b("body").append(m=b('<div id="fancybox-tmp"></div>'),t=b('<div id="fancybox-loading"><div></div></div>'),u=b('<div id="fancybox-overlay"></div>'),f=b('<div id="fancybox-wrap"></div>'));D=b('<div id="fancybox-outer"></div>').append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>').appendTo(f);
 44+D.append(j=b('<div id="fancybox-content"></div>'),E=b('<a id="fancybox-close"></a>'),n=b('<div id="fancybox-title"></div>'),z=b('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),A=b('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>'));E.click(b.fancybox.close);t.click(b.fancybox.cancel);z.click(function(a){a.preventDefault();b.fancybox.prev()});A.click(function(a){a.preventDefault();b.fancybox.next()});
 45+b.fn.mousewheel&&f.bind("mousewheel.fb",function(a,c){if(h)a.preventDefault();else if(b(a.target).get(0).clientHeight==0||b(a.target).get(0).scrollHeight===b(a.target).get(0).clientHeight){a.preventDefault();b.fancybox[c>0?"prev":"next"]()}});b.support.opacity||f.addClass("fancybox-ie");if(M){t.addClass("fancybox-ie6");f.addClass("fancybox-ie6");b('<iframe id="fancybox-hide-sel-frame" src="'+(/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank")+'" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(D)}}};
 46+b.fn.fancybox.defaults={padding:10,margin:40,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.7,overlayColor:"#777",titleShow:true,titlePosition:"float",titleFormat:null,titleFromAlt:false,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast",easingIn:"swing",
 47+easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,enableKeyboardNav:true,onStart:function(){},onCancel:function(){},onComplete:function(){},onCleanup:function(){},onClosed:function(){},onError:function(){}};b(document).ready(function(){b.fancybox.init()})})(jQuery);
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.fancybox-1.3.4.pack.js
___________________________________________________________________
Added: svn:eol-style
148 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_loading.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_loading.png
___________________________________________________________________
Added: svn:mime-type
249 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_title_right.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_title_right.png
___________________________________________________________________
Added: svn:mime-type
350 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.mousewheel-3.0.4.pack.js
@@ -0,0 +1,14 @@
 2+/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
 3+* Licensed under the MIT License (LICENSE.txt).
 4+*
 5+* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 6+* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 7+* Thanks to: Seamus Leahy for adding deltaX and deltaY
 8+*
 9+* Version: 3.0.4
 10+*
 11+* Requires: 1.2.2+
 12+*/
 13+
 14+(function(d){function g(a){var b=a||window.event,i=[].slice.call(arguments,1),c=0,h=0,e=0;a=d.event.fix(b);a.type="mousewheel";if(a.wheelDelta)c=a.wheelDelta/120;if(a.detail)c=-a.detail/3;e=c;if(b.axis!==undefined&&b.axis===b.HORIZONTAL_AXIS){e=0;h=-1*c}if(b.wheelDeltaY!==undefined)e=b.wheelDeltaY/120;if(b.wheelDeltaX!==undefined)h=-1*b.wheelDeltaX/120;i.unshift(a,c,h,e);return d.event.handle.apply(this,i)}var f=["DOMMouseScroll","mousewheel"];d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=
 15+f.length;a;)this.addEventListener(f[--a],g,false);else this.onmousewheel=g},teardown:function(){if(this.removeEventListener)for(var a=f.length;a;)this.removeEventListener(f[--a],g,false);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.mousewheel-3.0.4.pack.js
___________________________________________________________________
Added: svn:eol-style
116 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_nav_right.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_nav_right.png
___________________________________________________________________
Added: svn:mime-type
217 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_title_main.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_title_main.png
___________________________________________________________________
Added: svn:mime-type
318 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/blank.gif
Cannot display: file marked as a binary type.
svn:mime-type = image/gif
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/blank.gif
___________________________________________________________________
Added: svn:mime-type
419 + image/gif
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancybox.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancybox.png
___________________________________________________________________
Added: svn:mime-type
520 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_e.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_e.png
___________________________________________________________________
Added: svn:mime-type
621 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_nw.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_nw.png
___________________________________________________________________
Added: svn:mime-type
722 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_title_left.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_title_left.png
___________________________________________________________________
Added: svn:mime-type
823 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_nav_left.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_nav_left.png
___________________________________________________________________
Added: svn:mime-type
924 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_sw.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_sw.png
___________________________________________________________________
Added: svn:mime-type
1025 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancybox-x.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancybox-x.png
___________________________________________________________________
Added: svn:mime-type
1126 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancybox-y.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancybox-y.png
___________________________________________________________________
Added: svn:mime-type
1227 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.fancybox-1.3.4.js
@@ -0,0 +1,1156 @@
 2+/*
 3+ * FancyBox - jQuery Plugin
 4+ * Simple and fancy lightbox alternative
 5+ *
 6+ * Examples and documentation at: http://fancybox.net
 7+ *
 8+ * Copyright (c) 2008 - 2010 Janis Skarnelis
 9+ * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
 10+ *
 11+ * Version: 1.3.4 (11/11/2010)
 12+ * Requires: jQuery v1.3+
 13+ *
 14+ * Dual licensed under the MIT and GPL licenses:
 15+ * http://www.opensource.org/licenses/mit-license.php
 16+ * http://www.gnu.org/licenses/gpl.html
 17+ */
 18+
 19+;(function($) {
 20+ var tmp, loading, overlay, wrap, outer, content, close, title, nav_left, nav_right,
 21+
 22+ selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],
 23+
 24+ ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,
 25+
 26+ loadingTimer, loadingFrame = 1,
 27+
 28+ titleHeight = 0, titleStr = '', start_pos, final_pos, busy = false, fx = $.extend($('<div/>')[0], { prop: 0 }),
 29+
 30+ isIE6 = $.browser.msie && $.browser.version < 7 && !window.XMLHttpRequest,
 31+
 32+ /*
 33+ * Private methods
 34+ */
 35+
 36+ _abort = function() {
 37+ loading.hide();
 38+
 39+ imgPreloader.onerror = imgPreloader.onload = null;
 40+
 41+ if (ajaxLoader) {
 42+ ajaxLoader.abort();
 43+ }
 44+
 45+ tmp.empty();
 46+ },
 47+
 48+ _error = function() {
 49+ if (false === selectedOpts.onError(selectedArray, selectedIndex, selectedOpts)) {
 50+ loading.hide();
 51+ busy = false;
 52+ return;
 53+ }
 54+
 55+ selectedOpts.titleShow = false;
 56+
 57+ selectedOpts.width = 'auto';
 58+ selectedOpts.height = 'auto';
 59+
 60+ tmp.html( '<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>' );
 61+
 62+ _process_inline();
 63+ },
 64+
 65+ _start = function() {
 66+ var obj = selectedArray[ selectedIndex ],
 67+ href,
 68+ type,
 69+ title,
 70+ str,
 71+ emb,
 72+ ret;
 73+
 74+ _abort();
 75+
 76+ selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
 77+
 78+ ret = selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts);
 79+
 80+ if (ret === false) {
 81+ busy = false;
 82+ return;
 83+ } else if (typeof ret == 'object') {
 84+ selectedOpts = $.extend(selectedOpts, ret);
 85+ }
 86+
 87+ title = selectedOpts.title || (obj.nodeName ? $(obj).attr('title') : obj.title) || '';
 88+
 89+ if (obj.nodeName && !selectedOpts.orig) {
 90+ selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
 91+ }
 92+
 93+ if (title === '' && selectedOpts.orig && selectedOpts.titleFromAlt) {
 94+ title = selectedOpts.orig.attr('alt');
 95+ }
 96+
 97+ href = selectedOpts.href || (obj.nodeName ? $(obj).attr('href') : obj.href) || null;
 98+
 99+ if ((/^(?:javascript)/i).test(href) || href == '#') {
 100+ href = null;
 101+ }
 102+
 103+ if (selectedOpts.type) {
 104+ type = selectedOpts.type;
 105+
 106+ if (!href) {
 107+ href = selectedOpts.content;
 108+ }
 109+
 110+ } else if (selectedOpts.content) {
 111+ type = 'html';
 112+
 113+ } else if (href) {
 114+ if (href.match(imgRegExp)) {
 115+ type = 'image';
 116+
 117+ } else if (href.match(swfRegExp)) {
 118+ type = 'swf';
 119+
 120+ } else if ($(obj).hasClass("iframe")) {
 121+ type = 'iframe';
 122+
 123+ } else if (href.indexOf("#") === 0) {
 124+ type = 'inline';
 125+
 126+ } else {
 127+ type = 'ajax';
 128+ }
 129+ }
 130+
 131+ if (!type) {
 132+ _error();
 133+ return;
 134+ }
 135+
 136+ if (type == 'inline') {
 137+ obj = href.substr(href.indexOf("#"));
 138+ type = $(obj).length > 0 ? 'inline' : 'ajax';
 139+ }
 140+
 141+ selectedOpts.type = type;
 142+ selectedOpts.href = href;
 143+ selectedOpts.title = title;
 144+
 145+ if (selectedOpts.autoDimensions) {
 146+ if (selectedOpts.type == 'html' || selectedOpts.type == 'inline' || selectedOpts.type == 'ajax') {
 147+ selectedOpts.width = 'auto';
 148+ selectedOpts.height = 'auto';
 149+ } else {
 150+ selectedOpts.autoDimensions = false;
 151+ }
 152+ }
 153+
 154+ if (selectedOpts.modal) {
 155+ selectedOpts.overlayShow = true;
 156+ selectedOpts.hideOnOverlayClick = false;
 157+ selectedOpts.hideOnContentClick = false;
 158+ selectedOpts.enableEscapeButton = false;
 159+ selectedOpts.showCloseButton = false;
 160+ }
 161+
 162+ selectedOpts.padding = parseInt(selectedOpts.padding, 10);
 163+ selectedOpts.margin = parseInt(selectedOpts.margin, 10);
 164+
 165+ tmp.css('padding', (selectedOpts.padding + selectedOpts.margin));
 166+
 167+ $('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
 168+ $(this).replaceWith(content.children());
 169+ });
 170+
 171+ switch (type) {
 172+ case 'html' :
 173+ tmp.html( selectedOpts.content );
 174+ _process_inline();
 175+ break;
 176+
 177+ case 'inline' :
 178+ if ( $(obj).parent().is('#fancybox-content') === true) {
 179+ busy = false;
 180+ return;
 181+ }
 182+
 183+ $('<div class="fancybox-inline-tmp" />')
 184+ .hide()
 185+ .insertBefore( $(obj) )
 186+ .bind('fancybox-cleanup', function() {
 187+ $(this).replaceWith(content.children());
 188+ }).bind('fancybox-cancel', function() {
 189+ $(this).replaceWith(tmp.children());
 190+ });
 191+
 192+ $(obj).appendTo(tmp);
 193+
 194+ _process_inline();
 195+ break;
 196+
 197+ case 'image':
 198+ busy = false;
 199+
 200+ $.fancybox.showActivity();
 201+
 202+ imgPreloader = new Image();
 203+
 204+ imgPreloader.onerror = function() {
 205+ _error();
 206+ };
 207+
 208+ imgPreloader.onload = function() {
 209+ busy = true;
 210+
 211+ imgPreloader.onerror = imgPreloader.onload = null;
 212+
 213+ _process_image();
 214+ };
 215+
 216+ imgPreloader.src = href;
 217+ break;
 218+
 219+ case 'swf':
 220+ selectedOpts.scrolling = 'no';
 221+
 222+ str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
 223+ emb = '';
 224+
 225+ $.each(selectedOpts.swf, function(name, val) {
 226+ str += '<param name="' + name + '" value="' + val + '"></param>';
 227+ emb += ' ' + name + '="' + val + '"';
 228+ });
 229+
 230+ str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';
 231+
 232+ tmp.html(str);
 233+
 234+ _process_inline();
 235+ break;
 236+
 237+ case 'ajax':
 238+ busy = false;
 239+
 240+ $.fancybox.showActivity();
 241+
 242+ selectedOpts.ajax.win = selectedOpts.ajax.success;
 243+
 244+ ajaxLoader = $.ajax($.extend({}, selectedOpts.ajax, {
 245+ url : href,
 246+ data : selectedOpts.ajax.data || {},
 247+ error : function(XMLHttpRequest, textStatus, errorThrown) {
 248+ if ( XMLHttpRequest.status > 0 ) {
 249+ _error();
 250+ }
 251+ },
 252+ success : function(data, textStatus, XMLHttpRequest) {
 253+ var o = typeof XMLHttpRequest == 'object' ? XMLHttpRequest : ajaxLoader;
 254+ if (o.status == 200) {
 255+ if ( typeof selectedOpts.ajax.win == 'function' ) {
 256+ ret = selectedOpts.ajax.win(href, data, textStatus, XMLHttpRequest);
 257+
 258+ if (ret === false) {
 259+ loading.hide();
 260+ return;
 261+ } else if (typeof ret == 'string' || typeof ret == 'object') {
 262+ data = ret;
 263+ }
 264+ }
 265+
 266+ tmp.html( data );
 267+ _process_inline();
 268+ }
 269+ }
 270+ }));
 271+
 272+ break;
 273+
 274+ case 'iframe':
 275+ _show();
 276+ break;
 277+ }
 278+ },
 279+
 280+ _process_inline = function() {
 281+ var
 282+ w = selectedOpts.width,
 283+ h = selectedOpts.height;
 284+
 285+ if (w.toString().indexOf('%') > -1) {
 286+ w = parseInt( ($(window).width() - (selectedOpts.margin * 2)) * parseFloat(w) / 100, 10) + 'px';
 287+
 288+ } else {
 289+ w = w == 'auto' ? 'auto' : w + 'px';
 290+ }
 291+
 292+ if (h.toString().indexOf('%') > -1) {
 293+ h = parseInt( ($(window).height() - (selectedOpts.margin * 2)) * parseFloat(h) / 100, 10) + 'px';
 294+
 295+ } else {
 296+ h = h == 'auto' ? 'auto' : h + 'px';
 297+ }
 298+
 299+ tmp.wrapInner('<div style="width:' + w + ';height:' + h + ';overflow: ' + (selectedOpts.scrolling == 'auto' ? 'auto' : (selectedOpts.scrolling == 'yes' ? 'scroll' : 'hidden')) + ';position:relative;"></div>');
 300+
 301+ selectedOpts.width = tmp.width();
 302+ selectedOpts.height = tmp.height();
 303+
 304+ _show();
 305+ },
 306+
 307+ _process_image = function() {
 308+ selectedOpts.width = imgPreloader.width;
 309+ selectedOpts.height = imgPreloader.height;
 310+
 311+ $("<img />").attr({
 312+ 'id' : 'fancybox-img',
 313+ 'src' : imgPreloader.src,
 314+ 'alt' : selectedOpts.title
 315+ }).appendTo( tmp );
 316+
 317+ _show();
 318+ },
 319+
 320+ _show = function() {
 321+ var pos, equal;
 322+
 323+ loading.hide();
 324+
 325+ if (wrap.is(":visible") && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
 326+ $.event.trigger('fancybox-cancel');
 327+
 328+ busy = false;
 329+ return;
 330+ }
 331+
 332+ busy = true;
 333+
 334+ $(content.add( overlay )).unbind();
 335+
 336+ $(window).unbind("resize.fb scroll.fb");
 337+ $(document).unbind('keydown.fb');
 338+
 339+ if (wrap.is(":visible") && currentOpts.titlePosition !== 'outside') {
 340+ wrap.css('height', wrap.height());
 341+ }
 342+
 343+ currentArray = selectedArray;
 344+ currentIndex = selectedIndex;
 345+ currentOpts = selectedOpts;
 346+
 347+ if (currentOpts.overlayShow) {
 348+ overlay.css({
 349+ 'background-color' : currentOpts.overlayColor,
 350+ 'opacity' : currentOpts.overlayOpacity,
 351+ 'cursor' : currentOpts.hideOnOverlayClick ? 'pointer' : 'auto',
 352+ 'height' : $(document).height()
 353+ });
 354+
 355+ if (!overlay.is(':visible')) {
 356+ if (isIE6) {
 357+ $('select:not(#fancybox-tmp select)').filter(function() {
 358+ return this.style.visibility !== 'hidden';
 359+ }).css({'visibility' : 'hidden'}).one('fancybox-cleanup', function() {
 360+ this.style.visibility = 'inherit';
 361+ });
 362+ }
 363+
 364+ overlay.show();
 365+ }
 366+ } else {
 367+ overlay.hide();
 368+ }
 369+
 370+ final_pos = _get_zoom_to();
 371+
 372+ _process_title();
 373+
 374+ if (wrap.is(":visible")) {
 375+ $( close.add( nav_left ).add( nav_right ) ).hide();
 376+
 377+ pos = wrap.position(),
 378+
 379+ start_pos = {
 380+ top : pos.top,
 381+ left : pos.left,
 382+ width : wrap.width(),
 383+ height : wrap.height()
 384+ };
 385+
 386+ equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);
 387+
 388+ content.fadeTo(currentOpts.changeFade, 0.3, function() {
 389+ var finish_resizing = function() {
 390+ content.html( tmp.contents() ).fadeTo(currentOpts.changeFade, 1, _finish);
 391+ };
 392+
 393+ $.event.trigger('fancybox-change');
 394+
 395+ content
 396+ .empty()
 397+ .removeAttr('filter')
 398+ .css({
 399+ 'border-width' : currentOpts.padding,
 400+ 'width' : final_pos.width - currentOpts.padding * 2,
 401+ 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
 402+ });
 403+
 404+ if (equal) {
 405+ finish_resizing();
 406+
 407+ } else {
 408+ fx.prop = 0;
 409+
 410+ $(fx).animate({prop: 1}, {
 411+ duration : currentOpts.changeSpeed,
 412+ easing : currentOpts.easingChange,
 413+ step : _draw,
 414+ complete : finish_resizing
 415+ });
 416+ }
 417+ });
 418+
 419+ return;
 420+ }
 421+
 422+ wrap.removeAttr("style");
 423+
 424+ content.css('border-width', currentOpts.padding);
 425+
 426+ if (currentOpts.transitionIn == 'elastic') {
 427+ start_pos = _get_zoom_from();
 428+
 429+ content.html( tmp.contents() );
 430+
 431+ wrap.show();
 432+
 433+ if (currentOpts.opacity) {
 434+ final_pos.opacity = 0;
 435+ }
 436+
 437+ fx.prop = 0;
 438+
 439+ $(fx).animate({prop: 1}, {
 440+ duration : currentOpts.speedIn,
 441+ easing : currentOpts.easingIn,
 442+ step : _draw,
 443+ complete : _finish
 444+ });
 445+
 446+ return;
 447+ }
 448+
 449+ if (currentOpts.titlePosition == 'inside' && titleHeight > 0) {
 450+ title.show();
 451+ }
 452+
 453+ content
 454+ .css({
 455+ 'width' : final_pos.width - currentOpts.padding * 2,
 456+ 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
 457+ })
 458+ .html( tmp.contents() );
 459+
 460+ wrap
 461+ .css(final_pos)
 462+ .fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
 463+ },
 464+
 465+ _format_title = function(title) {
 466+ if (title && title.length) {
 467+ if (currentOpts.titlePosition == 'float') {
 468+ return '<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">' + title + '</td><td id="fancybox-title-float-right"></td></tr></table>';
 469+ }
 470+
 471+ return '<div id="fancybox-title-' + currentOpts.titlePosition + '">' + title + '</div>';
 472+ }
 473+
 474+ return false;
 475+ },
 476+
 477+ _process_title = function() {
 478+ titleStr = currentOpts.title || '';
 479+ titleHeight = 0;
 480+
 481+ title
 482+ .empty()
 483+ .removeAttr('style')
 484+ .removeClass();
 485+
 486+ if (currentOpts.titleShow === false) {
 487+ title.hide();
 488+ return;
 489+ }
 490+
 491+ titleStr = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(titleStr, currentArray, currentIndex, currentOpts) : _format_title(titleStr);
 492+
 493+ if (!titleStr || titleStr === '') {
 494+ title.hide();
 495+ return;
 496+ }
 497+
 498+ title
 499+ .addClass('fancybox-title-' + currentOpts.titlePosition)
 500+ .html( titleStr )
 501+ .appendTo( 'body' )
 502+ .show();
 503+
 504+ switch (currentOpts.titlePosition) {
 505+ case 'inside':
 506+ title
 507+ .css({
 508+ 'width' : final_pos.width - (currentOpts.padding * 2),
 509+ 'marginLeft' : currentOpts.padding,
 510+ 'marginRight' : currentOpts.padding
 511+ });
 512+
 513+ titleHeight = title.outerHeight(true);
 514+
 515+ title.appendTo( outer );
 516+
 517+ final_pos.height += titleHeight;
 518+ break;
 519+
 520+ case 'over':
 521+ title
 522+ .css({
 523+ 'marginLeft' : currentOpts.padding,
 524+ 'width' : final_pos.width - (currentOpts.padding * 2),
 525+ 'bottom' : currentOpts.padding
 526+ })
 527+ .appendTo( outer );
 528+ break;
 529+
 530+ case 'float':
 531+ title
 532+ .css('left', parseInt((title.width() - final_pos.width - 40)/ 2, 10) * -1)
 533+ .appendTo( wrap );
 534+ break;
 535+
 536+ default:
 537+ title
 538+ .css({
 539+ 'width' : final_pos.width - (currentOpts.padding * 2),
 540+ 'paddingLeft' : currentOpts.padding,
 541+ 'paddingRight' : currentOpts.padding
 542+ })
 543+ .appendTo( wrap );
 544+ break;
 545+ }
 546+
 547+ title.hide();
 548+ },
 549+
 550+ _set_navigation = function() {
 551+ if (currentOpts.enableEscapeButton || currentOpts.enableKeyboardNav) {
 552+ $(document).bind('keydown.fb', function(e) {
 553+ if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
 554+ e.preventDefault();
 555+ $.fancybox.close();
 556+
 557+ } else if ((e.keyCode == 37 || e.keyCode == 39) && currentOpts.enableKeyboardNav && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT') {
 558+ e.preventDefault();
 559+ $.fancybox[ e.keyCode == 37 ? 'prev' : 'next']();
 560+ }
 561+ });
 562+ }
 563+
 564+ if (!currentOpts.showNavArrows) {
 565+ nav_left.hide();
 566+ nav_right.hide();
 567+ return;
 568+ }
 569+
 570+ if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
 571+ nav_left.show();
 572+ }
 573+
 574+ if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
 575+ nav_right.show();
 576+ }
 577+ },
 578+
 579+ _finish = function () {
 580+ if (!$.support.opacity) {
 581+ content.get(0).style.removeAttribute('filter');
 582+ wrap.get(0).style.removeAttribute('filter');
 583+ }
 584+
 585+ if (selectedOpts.autoDimensions) {
 586+ content.css('height', 'auto');
 587+ }
 588+
 589+ wrap.css('height', 'auto');
 590+
 591+ if (titleStr && titleStr.length) {
 592+ title.show();
 593+ }
 594+
 595+ if (currentOpts.showCloseButton) {
 596+ close.show();
 597+ }
 598+
 599+ _set_navigation();
 600+
 601+ if (currentOpts.hideOnContentClick) {
 602+ content.bind('click', $.fancybox.close);
 603+ }
 604+
 605+ if (currentOpts.hideOnOverlayClick) {
 606+ overlay.bind('click', $.fancybox.close);
 607+ }
 608+
 609+ $(window).bind("resize.fb", $.fancybox.resize);
 610+
 611+ if (currentOpts.centerOnScroll) {
 612+ $(window).bind("scroll.fb", $.fancybox.center);
 613+ }
 614+
 615+ if (currentOpts.type == 'iframe') {
 616+ $('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" ' + ($.browser.msie ? 'allowtransparency="true""' : '') + ' scrolling="' + selectedOpts.scrolling + '" src="' + currentOpts.href + '"></iframe>').appendTo(content);
 617+ }
 618+
 619+ wrap.show();
 620+
 621+ busy = false;
 622+
 623+ $.fancybox.center();
 624+
 625+ currentOpts.onComplete(currentArray, currentIndex, currentOpts);
 626+
 627+ _preload_images();
 628+ },
 629+
 630+ _preload_images = function() {
 631+ var href,
 632+ objNext;
 633+
 634+ if ((currentArray.length -1) > currentIndex) {
 635+ href = currentArray[ currentIndex + 1 ].href;
 636+
 637+ if (typeof href !== 'undefined' && href.match(imgRegExp)) {
 638+ objNext = new Image();
 639+ objNext.src = href;
 640+ }
 641+ }
 642+
 643+ if (currentIndex > 0) {
 644+ href = currentArray[ currentIndex - 1 ].href;
 645+
 646+ if (typeof href !== 'undefined' && href.match(imgRegExp)) {
 647+ objNext = new Image();
 648+ objNext.src = href;
 649+ }
 650+ }
 651+ },
 652+
 653+ _draw = function(pos) {
 654+ var dim = {
 655+ width : parseInt(start_pos.width + (final_pos.width - start_pos.width) * pos, 10),
 656+ height : parseInt(start_pos.height + (final_pos.height - start_pos.height) * pos, 10),
 657+
 658+ top : parseInt(start_pos.top + (final_pos.top - start_pos.top) * pos, 10),
 659+ left : parseInt(start_pos.left + (final_pos.left - start_pos.left) * pos, 10)
 660+ };
 661+
 662+ if (typeof final_pos.opacity !== 'undefined') {
 663+ dim.opacity = pos < 0.5 ? 0.5 : pos;
 664+ }
 665+
 666+ wrap.css(dim);
 667+
 668+ content.css({
 669+ 'width' : dim.width - currentOpts.padding * 2,
 670+ 'height' : dim.height - (titleHeight * pos) - currentOpts.padding * 2
 671+ });
 672+ },
 673+
 674+ _get_viewport = function() {
 675+ return [
 676+ $(window).width() - (currentOpts.margin * 2),
 677+ $(window).height() - (currentOpts.margin * 2),
 678+ $(document).scrollLeft() + currentOpts.margin,
 679+ $(document).scrollTop() + currentOpts.margin
 680+ ];
 681+ },
 682+
 683+ _get_zoom_to = function () {
 684+ var view = _get_viewport(),
 685+ to = {},
 686+ resize = currentOpts.autoScale,
 687+ double_padding = currentOpts.padding * 2,
 688+ ratio;
 689+
 690+ if (currentOpts.width.toString().indexOf('%') > -1) {
 691+ to.width = parseInt((view[0] * parseFloat(currentOpts.width)) / 100, 10);
 692+ } else {
 693+ to.width = currentOpts.width + double_padding;
 694+ }
 695+
 696+ if (currentOpts.height.toString().indexOf('%') > -1) {
 697+ to.height = parseInt((view[1] * parseFloat(currentOpts.height)) / 100, 10);
 698+ } else {
 699+ to.height = currentOpts.height + double_padding;
 700+ }
 701+
 702+ if (resize && (to.width > view[0] || to.height > view[1])) {
 703+ if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
 704+ ratio = (currentOpts.width ) / (currentOpts.height );
 705+
 706+ if ((to.width ) > view[0]) {
 707+ to.width = view[0];
 708+ to.height = parseInt(((to.width - double_padding) / ratio) + double_padding, 10);
 709+ }
 710+
 711+ if ((to.height) > view[1]) {
 712+ to.height = view[1];
 713+ to.width = parseInt(((to.height - double_padding) * ratio) + double_padding, 10);
 714+ }
 715+
 716+ } else {
 717+ to.width = Math.min(to.width, view[0]);
 718+ to.height = Math.min(to.height, view[1]);
 719+ }
 720+ }
 721+
 722+ to.top = parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - to.height - 40) * 0.5)), 10);
 723+ to.left = parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - to.width - 40) * 0.5)), 10);
 724+
 725+ return to;
 726+ },
 727+
 728+ _get_obj_pos = function(obj) {
 729+ var pos = obj.offset();
 730+
 731+ pos.top += parseInt( obj.css('paddingTop'), 10 ) || 0;
 732+ pos.left += parseInt( obj.css('paddingLeft'), 10 ) || 0;
 733+
 734+ pos.top += parseInt( obj.css('border-top-width'), 10 ) || 0;
 735+ pos.left += parseInt( obj.css('border-left-width'), 10 ) || 0;
 736+
 737+ pos.width = obj.width();
 738+ pos.height = obj.height();
 739+
 740+ return pos;
 741+ },
 742+
 743+ _get_zoom_from = function() {
 744+ var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
 745+ from = {},
 746+ pos,
 747+ view;
 748+
 749+ if (orig && orig.length) {
 750+ pos = _get_obj_pos(orig);
 751+
 752+ from = {
 753+ width : pos.width + (currentOpts.padding * 2),
 754+ height : pos.height + (currentOpts.padding * 2),
 755+ top : pos.top - currentOpts.padding - 20,
 756+ left : pos.left - currentOpts.padding - 20
 757+ };
 758+
 759+ } else {
 760+ view = _get_viewport();
 761+
 762+ from = {
 763+ width : currentOpts.padding * 2,
 764+ height : currentOpts.padding * 2,
 765+ top : parseInt(view[3] + view[1] * 0.5, 10),
 766+ left : parseInt(view[2] + view[0] * 0.5, 10)
 767+ };
 768+ }
 769+
 770+ return from;
 771+ },
 772+
 773+ _animate_loading = function() {
 774+ if (!loading.is(':visible')){
 775+ clearInterval(loadingTimer);
 776+ return;
 777+ }
 778+
 779+ $('div', loading).css('top', (loadingFrame * -40) + 'px');
 780+
 781+ loadingFrame = (loadingFrame + 1) % 12;
 782+ };
 783+
 784+ /**
 785+ * Public methods
 786+ */
 787+
 788+ $.fn.fancybox = function(options) {
 789+ if (!$(this).length) {
 790+ return this;
 791+ }
 792+
 793+ $(this)
 794+ .data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
 795+ .unbind('click.fb')
 796+ .bind('click.fb', function(e) {
 797+ e.preventDefault();
 798+
 799+ if (busy) {
 800+ return;
 801+ }
 802+
 803+ busy = true;
 804+
 805+ $(this).blur();
 806+
 807+ selectedArray = [];
 808+ selectedIndex = 0;
 809+
 810+ var rel = $(this).attr('rel') || '';
 811+
 812+ if (!rel || rel == '' || rel === 'nofollow') {
 813+ selectedArray.push(this);
 814+
 815+ } else {
 816+ selectedArray = $("a[rel=" + rel + "], area[rel=" + rel + "]");
 817+ selectedIndex = selectedArray.index( this );
 818+ }
 819+
 820+ _start();
 821+
 822+ return;
 823+ });
 824+
 825+ return this;
 826+ };
 827+
 828+ $.fancybox = function(obj) {
 829+ var opts;
 830+
 831+ if (busy) {
 832+ return;
 833+ }
 834+
 835+ busy = true;
 836+ opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};
 837+
 838+ selectedArray = [];
 839+ selectedIndex = parseInt(opts.index, 10) || 0;
 840+
 841+ if ($.isArray(obj)) {
 842+ for (var i = 0, j = obj.length; i < j; i++) {
 843+ if (typeof obj[i] == 'object') {
 844+ $(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
 845+ } else {
 846+ obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
 847+ }
 848+ }
 849+
 850+ selectedArray = jQuery.merge(selectedArray, obj);
 851+
 852+ } else {
 853+ if (typeof obj == 'object') {
 854+ $(obj).data('fancybox', $.extend({}, opts, obj));
 855+ } else {
 856+ obj = $({}).data('fancybox', $.extend({content : obj}, opts));
 857+ }
 858+
 859+ selectedArray.push(obj);
 860+ }
 861+
 862+ if (selectedIndex > selectedArray.length || selectedIndex < 0) {
 863+ selectedIndex = 0;
 864+ }
 865+
 866+ _start();
 867+ };
 868+
 869+ $.fancybox.showActivity = function() {
 870+ clearInterval(loadingTimer);
 871+
 872+ loading.show();
 873+ loadingTimer = setInterval(_animate_loading, 66);
 874+ };
 875+
 876+ $.fancybox.hideActivity = function() {
 877+ loading.hide();
 878+ };
 879+
 880+ $.fancybox.next = function() {
 881+ return $.fancybox.pos( currentIndex + 1);
 882+ };
 883+
 884+ $.fancybox.prev = function() {
 885+ return $.fancybox.pos( currentIndex - 1);
 886+ };
 887+
 888+ $.fancybox.pos = function(pos) {
 889+ if (busy) {
 890+ return;
 891+ }
 892+
 893+ pos = parseInt(pos);
 894+
 895+ selectedArray = currentArray;
 896+
 897+ if (pos > -1 && pos < currentArray.length) {
 898+ selectedIndex = pos;
 899+ _start();
 900+
 901+ } else if (currentOpts.cyclic && currentArray.length > 1) {
 902+ selectedIndex = pos >= currentArray.length ? 0 : currentArray.length - 1;
 903+ _start();
 904+ }
 905+
 906+ return;
 907+ };
 908+
 909+ $.fancybox.cancel = function() {
 910+ if (busy) {
 911+ return;
 912+ }
 913+
 914+ busy = true;
 915+
 916+ $.event.trigger('fancybox-cancel');
 917+
 918+ _abort();
 919+
 920+ selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
 921+
 922+ busy = false;
 923+ };
 924+
 925+ // Note: within an iframe use - parent.$.fancybox.close();
 926+ $.fancybox.close = function() {
 927+ if (busy || wrap.is(':hidden')) {
 928+ return;
 929+ }
 930+
 931+ busy = true;
 932+
 933+ if (currentOpts && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
 934+ busy = false;
 935+ return;
 936+ }
 937+
 938+ _abort();
 939+
 940+ $(close.add( nav_left ).add( nav_right )).hide();
 941+
 942+ $(content.add( overlay )).unbind();
 943+
 944+ $(window).unbind("resize.fb scroll.fb");
 945+ $(document).unbind('keydown.fb');
 946+
 947+ content.find('iframe').attr('src', isIE6 && /^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank');
 948+
 949+ if (currentOpts.titlePosition !== 'inside') {
 950+ title.empty();
 951+ }
 952+
 953+ wrap.stop();
 954+
 955+ function _cleanup() {
 956+ overlay.fadeOut('fast');
 957+
 958+ title.empty().hide();
 959+ wrap.hide();
 960+
 961+ $.event.trigger('fancybox-cleanup');
 962+
 963+ content.empty();
 964+
 965+ currentOpts.onClosed(currentArray, currentIndex, currentOpts);
 966+
 967+ currentArray = selectedOpts = [];
 968+ currentIndex = selectedIndex = 0;
 969+ currentOpts = selectedOpts = {};
 970+
 971+ busy = false;
 972+ }
 973+
 974+ if (currentOpts.transitionOut == 'elastic') {
 975+ start_pos = _get_zoom_from();
 976+
 977+ var pos = wrap.position();
 978+
 979+ final_pos = {
 980+ top : pos.top ,
 981+ left : pos.left,
 982+ width : wrap.width(),
 983+ height : wrap.height()
 984+ };
 985+
 986+ if (currentOpts.opacity) {
 987+ final_pos.opacity = 1;
 988+ }
 989+
 990+ title.empty().hide();
 991+
 992+ fx.prop = 1;
 993+
 994+ $(fx).animate({ prop: 0 }, {
 995+ duration : currentOpts.speedOut,
 996+ easing : currentOpts.easingOut,
 997+ step : _draw,
 998+ complete : _cleanup
 999+ });
 1000+
 1001+ } else {
 1002+ wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
 1003+ }
 1004+ };
 1005+
 1006+ $.fancybox.resize = function() {
 1007+ if (overlay.is(':visible')) {
 1008+ overlay.css('height', $(document).height());
 1009+ }
 1010+
 1011+ $.fancybox.center(true);
 1012+ };
 1013+
 1014+ $.fancybox.center = function() {
 1015+ var view, align;
 1016+
 1017+ if (busy) {
 1018+ return;
 1019+ }
 1020+
 1021+ align = arguments[0] === true ? 1 : 0;
 1022+ view = _get_viewport();
 1023+
 1024+ if (!align && (wrap.width() > view[0] || wrap.height() > view[1])) {
 1025+ return;
 1026+ }
 1027+
 1028+ wrap
 1029+ .stop()
 1030+ .animate({
 1031+ 'top' : parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - content.height() - 40) * 0.5) - currentOpts.padding)),
 1032+ 'left' : parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - content.width() - 40) * 0.5) - currentOpts.padding))
 1033+ }, typeof arguments[0] == 'number' ? arguments[0] : 200);
 1034+ };
 1035+
 1036+ $.fancybox.init = function() {
 1037+ if ($("#fancybox-wrap").length) {
 1038+ return;
 1039+ }
 1040+
 1041+ $('body').append(
 1042+ tmp = $('<div id="fancybox-tmp"></div>'),
 1043+ loading = $('<div id="fancybox-loading"><div></div></div>'),
 1044+ overlay = $('<div id="fancybox-overlay"></div>'),
 1045+ wrap = $('<div id="fancybox-wrap"></div>')
 1046+ );
 1047+
 1048+ outer = $('<div id="fancybox-outer"></div>')
 1049+ .append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>')
 1050+ .appendTo( wrap );
 1051+
 1052+ outer.append(
 1053+ content = $('<div id="fancybox-content"></div>'),
 1054+ close = $('<a id="fancybox-close"></a>'),
 1055+ title = $('<div id="fancybox-title"></div>'),
 1056+
 1057+ nav_left = $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
 1058+ nav_right = $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
 1059+ );
 1060+
 1061+ close.click($.fancybox.close);
 1062+ loading.click($.fancybox.cancel);
 1063+
 1064+ nav_left.click(function(e) {
 1065+ e.preventDefault();
 1066+ $.fancybox.prev();
 1067+ });
 1068+
 1069+ nav_right.click(function(e) {
 1070+ e.preventDefault();
 1071+ $.fancybox.next();
 1072+ });
 1073+
 1074+ if ($.fn.mousewheel) {
 1075+ wrap.bind('mousewheel.fb', function(e, delta) {
 1076+ if (busy) {
 1077+ e.preventDefault();
 1078+
 1079+ } else if ($(e.target).get(0).clientHeight == 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) {
 1080+ e.preventDefault();
 1081+ $.fancybox[ delta > 0 ? 'prev' : 'next']();
 1082+ }
 1083+ });
 1084+ }
 1085+
 1086+ if (!$.support.opacity) {
 1087+ wrap.addClass('fancybox-ie');
 1088+ }
 1089+
 1090+ if (isIE6) {
 1091+ loading.addClass('fancybox-ie6');
 1092+ wrap.addClass('fancybox-ie6');
 1093+
 1094+ $('<iframe id="fancybox-hide-sel-frame" src="' + (/^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank' ) + '" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(outer);
 1095+ }
 1096+ };
 1097+
 1098+ $.fn.fancybox.defaults = {
 1099+ padding : 10,
 1100+ margin : 40,
 1101+ opacity : false,
 1102+ modal : false,
 1103+ cyclic : false,
 1104+ scrolling : 'auto', // 'auto', 'yes' or 'no'
 1105+
 1106+ width : 560,
 1107+ height : 340,
 1108+
 1109+ autoScale : true,
 1110+ autoDimensions : true,
 1111+ centerOnScroll : false,
 1112+
 1113+ ajax : {},
 1114+ swf : { wmode: 'transparent' },
 1115+
 1116+ hideOnOverlayClick : true,
 1117+ hideOnContentClick : false,
 1118+
 1119+ overlayShow : true,
 1120+ overlayOpacity : 0.7,
 1121+ overlayColor : '#777',
 1122+
 1123+ titleShow : true,
 1124+ titlePosition : 'float', // 'float', 'outside', 'inside' or 'over'
 1125+ titleFormat : null,
 1126+ titleFromAlt : false,
 1127+
 1128+ transitionIn : 'fade', // 'elastic', 'fade' or 'none'
 1129+ transitionOut : 'fade', // 'elastic', 'fade' or 'none'
 1130+
 1131+ speedIn : 300,
 1132+ speedOut : 300,
 1133+
 1134+ changeSpeed : 300,
 1135+ changeFade : 'fast',
 1136+
 1137+ easingIn : 'swing',
 1138+ easingOut : 'swing',
 1139+
 1140+ showCloseButton : true,
 1141+ showNavArrows : true,
 1142+ enableEscapeButton : true,
 1143+ enableKeyboardNav : true,
 1144+
 1145+ onStart : function(){},
 1146+ onCancel : function(){},
 1147+ onComplete : function(){},
 1148+ onCleanup : function(){},
 1149+ onClosed : function(){},
 1150+ onError : function(){}
 1151+ };
 1152+
 1153+ $(document).ready(function() {
 1154+ $.fancybox.init();
 1155+ });
 1156+
 1157+})(jQuery);
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.fancybox-1.3.4.js
___________________________________________________________________
Added: svn:eol-style
11158 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_n.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_n.png
___________________________________________________________________
Added: svn:mime-type
21159 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_close.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_close.png
___________________________________________________________________
Added: svn:mime-type
31160 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_s.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_s.png
___________________________________________________________________
Added: svn:mime-type
41161 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_ne.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_ne.png
___________________________________________________________________
Added: svn:mime-type
51162 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.easing-1.3.pack.js
@@ -0,0 +1,72 @@
 2+/*
 3+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 4+ *
 5+ * Uses the built in easing capabilities added In jQuery 1.1
 6+ * to offer multiple easing options
 7+ *
 8+ * TERMS OF USE - jQuery Easing
 9+ *
 10+ * Open source under the BSD License.
 11+ *
 12+ * Copyright © 2008 George McGinley Smith
 13+ * All rights reserved.
 14+ *
 15+ * Redistribution and use in source and binary forms, with or without modification,
 16+ * are permitted provided that the following conditions are met:
 17+ *
 18+ * Redistributions of source code must retain the above copyright notice, this list of
 19+ * conditions and the following disclaimer.
 20+ * Redistributions in binary form must reproduce the above copyright notice, this list
 21+ * of conditions and the following disclaimer in the documentation and/or other materials
 22+ * provided with the distribution.
 23+ *
 24+ * Neither the name of the author nor the names of contributors may be used to endorse
 25+ * or promote products derived from this software without specific prior written permission.
 26+ *
 27+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 28+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 29+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 30+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 31+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 32+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 33+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 34+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 35+ * OF THE POSSIBILITY OF SUCH DAMAGE.
 36+ *
 37+*/
 38+
 39+// t: current time, b: begInnIng value, c: change In value, d: duration
 40+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('h.i[\'1a\']=h.i[\'z\'];h.O(h.i,{y:\'D\',z:9(x,t,b,c,d){6 h.i[h.i.y](x,t,b,c,d)},17:9(x,t,b,c,d){6 c*(t/=d)*t+b},D:9(x,t,b,c,d){6-c*(t/=d)*(t-2)+b},13:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t+b;6-c/2*((--t)*(t-2)-1)+b},X:9(x,t,b,c,d){6 c*(t/=d)*t*t+b},U:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t+1)+b},R:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t+b;6 c/2*((t-=2)*t*t+2)+b},N:9(x,t,b,c,d){6 c*(t/=d)*t*t*t+b},M:9(x,t,b,c,d){6-c*((t=t/d-1)*t*t*t-1)+b},L:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t+b;6-c/2*((t-=2)*t*t*t-2)+b},K:9(x,t,b,c,d){6 c*(t/=d)*t*t*t*t+b},J:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t*t*t+1)+b},I:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t*t+b;6 c/2*((t-=2)*t*t*t*t+2)+b},G:9(x,t,b,c,d){6-c*8.C(t/d*(8.g/2))+c+b},15:9(x,t,b,c,d){6 c*8.n(t/d*(8.g/2))+b},12:9(x,t,b,c,d){6-c/2*(8.C(8.g*t/d)-1)+b},Z:9(x,t,b,c,d){6(t==0)?b:c*8.j(2,10*(t/d-1))+b},Y:9(x,t,b,c,d){6(t==d)?b+c:c*(-8.j(2,-10*t/d)+1)+b},W:9(x,t,b,c,d){e(t==0)6 b;e(t==d)6 b+c;e((t/=d/2)<1)6 c/2*8.j(2,10*(t-1))+b;6 c/2*(-8.j(2,-10*--t)+2)+b},V:9(x,t,b,c,d){6-c*(8.o(1-(t/=d)*t)-1)+b},S:9(x,t,b,c,d){6 c*8.o(1-(t=t/d-1)*t)+b},Q:9(x,t,b,c,d){e((t/=d/2)<1)6-c/2*(8.o(1-t*t)-1)+b;6 c/2*(8.o(1-(t-=2)*t)+1)+b},P:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6-(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b},H:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6 a*8.j(2,-10*t)*8.n((t*d-s)*(2*8.g)/p)+c+b},T:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d/2)==2)6 b+c;e(!p)p=d*(.3*1.5);e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);e(t<1)6-.5*(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b;6 a*8.j(2,-10*(t-=1))*8.n((t*d-s)*(2*8.g)/p)*.5+c+b},F:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*(t/=d)*t*((s+1)*t-s)+b},E:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*((t=t/d-1)*t*((s+1)*t+s)+1)+b},16:9(x,t,b,c,d,s){e(s==u)s=1.l;e((t/=d/2)<1)6 c/2*(t*t*(((s*=(1.B))+1)*t-s))+b;6 c/2*((t-=2)*t*(((s*=(1.B))+1)*t+s)+2)+b},A:9(x,t,b,c,d){6 c-h.i.v(x,d-t,0,c,d)+b},v:9(x,t,b,c,d){e((t/=d)<(1/2.k)){6 c*(7.q*t*t)+b}m e(t<(2/2.k)){6 c*(7.q*(t-=(1.5/2.k))*t+.k)+b}m e(t<(2.5/2.k)){6 c*(7.q*(t-=(2.14/2.k))*t+.11)+b}m{6 c*(7.q*(t-=(2.18/2.k))*t+.19)+b}},1b:9(x,t,b,c,d){e(t<d/2)6 h.i.A(x,t*2,0,c,d)*.5+b;6 h.i.v(x,t*2-d,0,c,d)*.5+c*.5+b}});',62,74,'||||||return||Math|function|||||if|var|PI|jQuery|easing|pow|75|70158|else|sin|sqrt||5625|asin|||undefined|easeOutBounce|abs||def|swing|easeInBounce|525|cos|easeOutQuad|easeOutBack|easeInBack|easeInSine|easeOutElastic|easeInOutQuint|easeOutQuint|easeInQuint|easeInOutQuart|easeOutQuart|easeInQuart|extend|easeInElastic|easeInOutCirc|easeInOutCubic|easeOutCirc|easeInOutElastic|easeOutCubic|easeInCirc|easeInOutExpo|easeInCubic|easeOutExpo|easeInExpo||9375|easeInOutSine|easeInOutQuad|25|easeOutSine|easeInOutBack|easeInQuad|625|984375|jswing|easeInOutBounce'.split('|'),0,{}))
 41+
 42+/*
 43+ *
 44+ * TERMS OF USE - EASING EQUATIONS
 45+ *
 46+ * Open source under the BSD License.
 47+ *
 48+ * Copyright © 2001 Robert Penner
 49+ * All rights reserved.
 50+ *
 51+ * Redistribution and use in source and binary forms, with or without modification,
 52+ * are permitted provided that the following conditions are met:
 53+ *
 54+ * Redistributions of source code must retain the above copyright notice, this list of
 55+ * conditions and the following disclaimer.
 56+ * Redistributions in binary form must reproduce the above copyright notice, this list
 57+ * of conditions and the following disclaimer in the documentation and/or other materials
 58+ * provided with the distribution.
 59+ *
 60+ * Neither the name of the author nor the names of contributors may be used to endorse
 61+ * or promote products derived from this software without specific prior written permission.
 62+ *
 63+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 64+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 65+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 66+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 67+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 68+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 69+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 70+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 71+ * OF THE POSSIBILITY OF SUCH DAMAGE.
 72+ *
 73+ */
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/jquery.easing-1.3.pack.js
___________________________________________________________________
Added: svn:eol-style
174 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_w.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/fancybox/fancy_shadow_w.png
___________________________________________________________________
Added: svn:mime-type
275 + image/png
Index: tags/extensions/Survey/REL_0_1_2/resources/jquery.numeric.js
@@ -0,0 +1,279 @@
 2+/*
 3+ *
 4+ * Copyright (c) 2006-2011 Sam Collett (http://www.texotela.co.uk)
 5+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 6+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 7+ *
 8+ * Version 1.3
 9+ * Demo: http://www.texotela.co.uk/code/jquery/numeric/
 10+ *
 11+ */
 12+(function($) {
 13+/*
 14+ * Allows only valid characters to be entered into input boxes.
 15+ * Note: fixes value when pasting via Ctrl+V, but not when using the mouse to paste
 16+ * side-effect: Ctrl+A does not work, though you can still use the mouse to select (or double-click to select all)
 17+ *
 18+ * @name numeric
 19+ * @param config { decimal : "." , negative : true }
 20+ * @param callback A function that runs if the number is not valid (fires onblur)
 21+ * @author Sam Collett (http://www.texotela.co.uk)
 22+ * @example $(".numeric").numeric();
 23+ * @example $(".numeric").numeric(","); // use , as separater
 24+ * @example $(".numeric").numeric({ decimal : "," }); // use , as separator
 25+ * @example $(".numeric").numeric({ negative : false }); // do not allow negative values
 26+ * @example $(".numeric").numeric(null, callback); // use default values, pass on the 'callback' function
 27+ *
 28+ */
 29+$.fn.numeric = function(config, callback)
 30+{
 31+ if(typeof config === 'boolean')
 32+ {
 33+ config = { decimal: config };
 34+ }
 35+ config = config || {};
 36+ // if config.negative undefined, set to true (default is to allow negative numbers)
 37+ if(typeof config.negative == "undefined") config.negative = true;
 38+ // set decimal point
 39+ var decimal = (config.decimal === false) ? "" : config.decimal || ".";
 40+ // allow negatives
 41+ var negative = (config.negative === true) ? true : false;
 42+ // callback function
 43+ var callback = typeof callback == "function" ? callback : function(){};
 44+ // set data and methods
 45+ return this.data("numeric.decimal", decimal).data("numeric.negative", negative).data("numeric.callback", callback).keypress($.fn.numeric.keypress).keyup($.fn.numeric.keyup).blur($.fn.numeric.blur);
 46+}
 47+
 48+$.fn.numeric.keypress = function(e)
 49+{
 50+ // get decimal character and determine if negatives are allowed
 51+ var decimal = $.data(this, "numeric.decimal");
 52+ var negative = $.data(this, "numeric.negative");
 53+ // get the key that was pressed
 54+ var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
 55+ // allow enter/return key (only when in an input box)
 56+ if(key == 13 && this.nodeName.toLowerCase() == "input")
 57+ {
 58+ return true;
 59+ }
 60+ else if(key == 13)
 61+ {
 62+ return false;
 63+ }
 64+ var allow = false;
 65+ // allow Ctrl+A
 66+ if((e.ctrlKey && key == 97 /* firefox */) || (e.ctrlKey && key == 65) /* opera */) return true;
 67+ // allow Ctrl+X (cut)
 68+ if((e.ctrlKey && key == 120 /* firefox */) || (e.ctrlKey && key == 88) /* opera */) return true;
 69+ // allow Ctrl+C (copy)
 70+ if((e.ctrlKey && key == 99 /* firefox */) || (e.ctrlKey && key == 67) /* opera */) return true;
 71+ // allow Ctrl+Z (undo)
 72+ if((e.ctrlKey && key == 122 /* firefox */) || (e.ctrlKey && key == 90) /* opera */) return true;
 73+ // allow or deny Ctrl+V (paste), Shift+Ins
 74+ if((e.ctrlKey && key == 118 /* firefox */) || (e.ctrlKey && key == 86) /* opera */
 75+ || (e.shiftKey && key == 45)) return true;
 76+ // if a number was not pressed
 77+ if(key < 48 || key > 57)
 78+ {
 79+ /* '-' only allowed at start and if negative numbers allowed */
 80+ if(this.value.indexOf("-") != 0 && negative && key == 45 && (this.value.length == 0 || ($.fn.getSelectionStart(this)) == 0)) return true;
 81+ /* only one decimal separator allowed */
 82+ if(decimal && key == decimal.charCodeAt(0) && this.value.indexOf(decimal) != -1)
 83+ {
 84+ allow = false;
 85+ }
 86+ // check for other keys that have special purposes
 87+ if(
 88+ key != 8 /* backspace */ &&
 89+ key != 9 /* tab */ &&
 90+ key != 13 /* enter */ &&
 91+ key != 35 /* end */ &&
 92+ key != 36 /* home */ &&
 93+ key != 37 /* left */ &&
 94+ key != 39 /* right */ &&
 95+ key != 46 /* del */
 96+ )
 97+ {
 98+ allow = false;
 99+ }
 100+ else
 101+ {
 102+ // for detecting special keys (listed above)
 103+ // IE does not support 'charCode' and ignores them in keypress anyway
 104+ if(typeof e.charCode != "undefined")
 105+ {
 106+ // special keys have 'keyCode' and 'which' the same (e.g. backspace)
 107+ if(e.keyCode == e.which && e.which != 0)
 108+ {
 109+ allow = true;
 110+ // . and delete share the same code, don't allow . (will be set to true later if it is the decimal point)
 111+ if(e.which == 46) allow = false;
 112+ }
 113+ // or keyCode != 0 and 'charCode'/'which' = 0
 114+ else if(e.keyCode != 0 && e.charCode == 0 && e.which == 0)
 115+ {
 116+ allow = true;
 117+ }
 118+ }
 119+ }
 120+ // if key pressed is the decimal and it is not already in the field
 121+ if(decimal && key == decimal.charCodeAt(0))
 122+ {
 123+ if(this.value.indexOf(decimal) == -1)
 124+ {
 125+ allow = true;
 126+ }
 127+ else
 128+ {
 129+ allow = false;
 130+ }
 131+ }
 132+ }
 133+ else
 134+ {
 135+ allow = true;
 136+ }
 137+ return allow;
 138+}
 139+
 140+$.fn.numeric.keyup = function(e)
 141+{
 142+ var val = this.value;
 143+ if(val.length > 0)
 144+ {
 145+ // get carat (cursor) position
 146+ var carat = $.fn.getSelectionStart(this);
 147+ // get decimal character and determine if negatives are allowed
 148+ var decimal = $.data(this, "numeric.decimal");
 149+ var negative = $.data(this, "numeric.negative");
 150+
 151+ // prepend a 0 if necessary
 152+ if(decimal != "")
 153+ {
 154+ // find decimal point
 155+ var dot = val.indexOf(decimal);
 156+ // if dot at start, add 0 before
 157+ if(dot == 0)
 158+ {
 159+ this.value = "0" + val;
 160+ }
 161+ // if dot at position 1, check if there is a - symbol before it
 162+ if(dot == 1 && val.charAt(0) == "-")
 163+ {
 164+ this.value = "-0" + val.substring(1);
 165+ }
 166+ val = this.value;
 167+ }
 168+
 169+ // if pasted in, only allow the following characters
 170+ var validChars = [0,1,2,3,4,5,6,7,8,9,'-',decimal];
 171+ // get length of the value (to loop through)
 172+ var length = val.length;
 173+ // loop backwards (to prevent going out of bounds)
 174+ for(var i = length - 1; i >= 0; i--)
 175+ {
 176+ var ch = val.charAt(i);
 177+ // remove '-' if it is in the wrong place
 178+ if(i != 0 && ch == "-")
 179+ {
 180+ val = val.substring(0, i) + val.substring(i + 1);
 181+ }
 182+ // remove character if it is at the start, a '-' and negatives aren't allowed
 183+ else if(i == 0 && !negative && ch == "-")
 184+ {
 185+ val = val.substring(1);
 186+ }
 187+ var validChar = false;
 188+ // loop through validChars
 189+ for(var j = 0; j < validChars.length; j++)
 190+ {
 191+ // if it is valid, break out the loop
 192+ if(ch == validChars[j])
 193+ {
 194+ validChar = true;
 195+ break;
 196+ }
 197+ }
 198+ // if not a valid character, or a space, remove
 199+ if(!validChar || ch == " ")
 200+ {
 201+ val = val.substring(0, i) + val.substring(i + 1);
 202+ }
 203+ }
 204+ // remove extra decimal characters
 205+ var firstDecimal = val.indexOf(decimal);
 206+ if(firstDecimal > 0)
 207+ {
 208+ for(var i = length - 1; i > firstDecimal; i--)
 209+ {
 210+ var ch = val.charAt(i);
 211+ // remove decimal character
 212+ if(ch == decimal)
 213+ {
 214+ val = val.substring(0, i) + val.substring(i + 1);
 215+ }
 216+ }
 217+ }
 218+ // set the value and prevent the cursor moving to the end
 219+ this.value = val;
 220+ $.fn.setSelection(this, carat);
 221+ }
 222+}
 223+
 224+$.fn.numeric.blur = function()
 225+{
 226+ var decimal = $.data(this, "numeric.decimal");
 227+ var callback = $.data(this, "numeric.callback");
 228+ var val = this.value;
 229+ if(val != "")
 230+ {
 231+ var re = new RegExp("^\\d+$|\\d*" + decimal + "\\d+");
 232+ if(!re.exec(val))
 233+ {
 234+ callback.apply(this);
 235+ }
 236+ }
 237+}
 238+
 239+$.fn.removeNumeric = function()
 240+{
 241+ return this.data("numeric.decimal", null).data("numeric.negative", null).data("numeric.callback", null).unbind("keypress", $.fn.numeric.keypress).unbind("blur", $.fn.numeric.blur);
 242+}
 243+
 244+// Based on code from http://javascript.nwbox.com/cursor_position/ (Diego Perini <dperini@nwbox.com>)
 245+$.fn.getSelectionStart = function(o)
 246+{
 247+ if (o.createTextRange)
 248+ {
 249+ var r = document.selection.createRange().duplicate();
 250+ r.moveEnd('character', o.value.length);
 251+ if (r.text == '') return o.value.length;
 252+ return o.value.lastIndexOf(r.text);
 253+ } else return o.selectionStart;
 254+}
 255+
 256+// set the selection, o is the object (input), p is the position ([start, end] or just start)
 257+$.fn.setSelection = function(o, p)
 258+{
 259+ // if p is number, start and end are the same
 260+ if(typeof p == "number") p = [p, p];
 261+ // only set if p is an array of length 2
 262+ if(p && p.constructor == Array && p.length == 2)
 263+ {
 264+ if (o.createTextRange)
 265+ {
 266+ var r = o.createTextRange();
 267+ r.collapse(true);
 268+ r.moveStart('character', p[0]);
 269+ r.moveEnd('character', p[1]);
 270+ r.select();
 271+ }
 272+ else if(o.setSelectionRange)
 273+ {
 274+ o.focus();
 275+ o.setSelectionRange(p[0], p[1]);
 276+ }
 277+ }
 278+}
 279+
 280+})(jQuery);
\ No newline at end of file
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/jquery.numeric.js
___________________________________________________________________
Added: svn:eol-style
1281 + native
Index: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.special.survey.css
@@ -0,0 +1,5 @@
 2+@CHARSET "UTF-8";
 3+
 4+td .question-label {
 5+ vertical-align: middle;
 6+}
Property changes on: tags/extensions/Survey/REL_0_1_2/resources/ext.survey.special.survey.css
___________________________________________________________________
Added: svn:eol-style
17 + native
Index: tags/extensions/Survey/REL_0_1_2/Survey.alias.php
@@ -0,0 +1,23 @@
 2+<?php
 3+
 4+/**
 5+ * Aliases for the special pages of the Survey extension.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file Survey.alias.php
 10+ * @ingroup Survey
 11+ *
 12+ * @licence GNU GPL v3+
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+
 16+$specialPageAliases = array();
 17+
 18+/** English (English) */
 19+$specialPageAliases['en'] = array(
 20+ 'EditSurvey' => array( 'EditSurvey', 'Survey' ),
 21+ 'Surveys' => array( 'Surveys' ),
 22+ 'SurveyStats' => array( 'SurveyStats', 'SurveyStatistics' ),
 23+ 'TakeSurvey' => array( 'TakeSurvey' ),
 24+);
Property changes on: tags/extensions/Survey/REL_0_1_2/Survey.alias.php
___________________________________________________________________
Added: svn:eol-style
125 + native

Status & tagging log