Full Code of kdzwinel/Context for AI

master fc92e393633e cached
65 files
19.7 MB
56.0k tokens
59 symbols
1 requests
Download .txt
Showing preview only (214K chars total). Download the full file or copy to clipboard to get everything.
Repository: kdzwinel/Context
Branch: master
Commit: fc92e393633e
Files: 65
Total size: 19.7 MB

Directory structure:
gitextract_q4srk3q8/

├── .editorconfig
├── .gitignore
├── Gruntfile.js
├── README.md
├── _locales/
│   ├── cleanup.php
│   ├── de/
│   │   └── messages.json
│   ├── en/
│   │   └── messages.json
│   ├── es/
│   │   └── messages.json
│   ├── fr/
│   │   └── messages.json
│   ├── it/
│   │   ├── description.txt
│   │   └── messages.json
│   ├── ja/
│   │   └── messages.json
│   ├── pl/
│   │   └── messages.json
│   ├── pt_BR/
│   │   └── messages.json
│   └── zh_CN/
│       └── messages.json
├── background.html
├── css/
│   ├── main.css
│   └── ui-lightness/
│       └── jquery-ui-1.8.17.custom.css
├── gfx/
│   ├── icon/
│   │   ├── ampoules/
│   │   │   ├── ampoules-icon-colors-condensed.xcf
│   │   │   └── ampoules-icon-colors.xcf
│   │   ├── context/
│   │   │   └── context.xcf
│   │   ├── intersec/
│   │   │   └── intersec-128.xcf
│   │   └── puzzle_next/
│   │       ├── puzzle_silver.xcf
│   │       ├── puzzle_silver_cog.xcf
│   │       └── puzzle_silver_cogs.xcf
│   ├── promo/
│   │   ├── context-128.xcf
│   │   ├── context-64.xcf
│   │   ├── large-promo-icons.xcf
│   │   ├── large-promo-less-icons.xcf
│   │   ├── large-promo.xcf
│   │   └── small-promo.xcf
│   ├── screenshots/
│   │   ├── step_1_en.xcf
│   │   ├── step_1_pl.xcf
│   │   ├── step_2_en.xcf
│   │   ├── step_2_pl.xcf
│   │   ├── step_3_en.xcf
│   │   ├── step_3_pl.xcf
│   │   ├── step_4_en.xcf
│   │   └── step_4_pl.xcf
│   └── webstore-scr/
│       ├── cn/
│       │   └── old_xcf/
│       │       ├── first.xcf
│       │       ├── grouping.xcf
│       │       └── popup.xcf
│       ├── first.xcf
│       ├── grouping.xcf
│       └── popup.xcf
├── js/
│   ├── background.js
│   ├── classes/
│   │   ├── Configuration.class.js
│   │   ├── ConfigurationBackupExporter.class.js
│   │   ├── ConfigurationBackupImporter.class.js
│   │   ├── ContextsManager.class.js
│   │   ├── ExtensionNotification.class.js
│   │   ├── ExtensionsManager.class.js
│   │   ├── HugeStorageSync.class.js
│   │   └── IconAnimation.class.js
│   ├── libs/
│   │   └── Base64.js
│   ├── notification.js
│   ├── options/
│   │   ├── dialogs.js
│   │   ├── firstrun.js
│   │   └── main.js
│   └── popup.js
├── manifest.json
├── notification.html
├── options.html
├── package.json
└── popup.html

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

# Default charset
[*]
charset = utf-8

# Tab indentation (no size specified)
[*]
indent_style = tab

================================================
FILE: .gitignore
================================================
*~
nbproject
.DS_Store
.idea


================================================
FILE: Gruntfile.js
================================================
module.exports = function(grunt) {
	"use strict";

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		jshint: {
			files: ['Gruntfile.js', 'js/**/*.js', '!js/libs/*.js'],
			options: {
				evil: true,
				camelcase: true,
				curly: true,
				eqeqeq: true,
				noempty: true,
				strict: true,
				loopfunc: true,
				globals: {
					jQuery: true,
					console: true,
					document: true
				}
			}
		},
		csslint: {
			src: ['css/*.css'],
			options: {
				ids: false,
				'compatible-vendor-prefixes': false,
				'fallback-colors': false
			}
		},
		validation: {
			options: {
				reset: true,
				reportpath: false
			},
			files: {
				src: ['*.html']
			}
		},
		zip: {
			'context-<%= pkg.version %>.zip': ['_locales/*/messages.json', 'css/**/*', 'screenshots/**/*.jpg', 'icons/**/*.png', 'js/**/*', 'other/**/*', '*.html', 'manifest.json']
		}
	});

	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-csslint');
	grunt.loadNpmTasks('grunt-html-validation');
	grunt.loadNpmTasks('grunt-zip');

	grunt.registerTask('default', ['jshint', 'csslint', 'validation']);
	grunt.registerTask('prod', ['zip']);
};

================================================
FILE: README.md
================================================
Context
======================

Chrome/Chromium extension that allows to sort other extensions into groups and easily switch between them.

Usage
-----

You may install this extension from its google chrome webstore page

https://chrome.google.com/webstore/detail/aalnjolghjkkogicompabhhbbkljnlka

or download it and manually load as an 'Unpacked extension' via chrome extensions page.


Bugs and Features
-----------------

If you found a bug or have a feature request, please create an issue here on GitHub.

https://github.com/kdzwinel/Context/issues

Changelog
---------

### 0.410 ###

New features:
+ Ability to manage individual extensions from the popup (#29)

Bug fixes:
+ options page not responding - replacing webkitNotifications with Chrome notifications / HTML5 notifications

Other:
+ Grunt support

### 0.400 ###

New features:
+ syncing configuration via Chrome Sync
+ displaying status of each context in the popup (enabled-green/disabled-red/partial-yellow)
+ displaying status of extensions on the options page (enabled-red/disabled-green)
+ possibility to use extension icon instead of context icon
+ preserving state of 'highlight ungrouped extensions' checkbox

Bugs fixed:
+ cloned context partially inactive until options page was refreshed

Other:
+ Thanks to Thiago Talma (@thiagomt) who contributed huge part of this update.
+ Disabling 'ask what to do' option for browsers that no longer support HTML notifications (#23)
+ Codebase improved thanks to the WebStorm

### 0.300 ###

New features:
+ importing/exporting configuration
+ highlighting ungrouped extensions on options page
+ new default action for new extensions: 'add to always-enabled'
+ new action in notification window: 'add to always-enabled'

Bugs fixed:
+ notification window showing up when no contexts are available
+ formatting bug in notification window

Other:
+ core functionality was rewritten using OOP (still far from perfect though)

### 0.200 ###

New features:
+ enabling/disabling multiple contexts ("+" and "-" buttons in the popup)
+ possibility to duplicate contexts on options page
+ always enabled extensions

Author
------

**Konrad Dzwinel**

+ https://github.com/kdzwinel
+ http://www.linkedin.com/pub/konrad-dzwinel/53/599/366/en

License
-------

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.


================================================
FILE: _locales/cleanup.php
================================================
<?php
/**
* This script reads translation files and fixes them by:
* - adding missing keys (basing on english translation)
* - cleaning up file formatting
* - checking for key duplicates
* - maintaining the same key order in all translation files
*
* REQUIRES PHP 5 >= 5.4 to run
*/

function json_readable_encode($in, $indent = 0) {
    $_myself = __FUNCTION__;
    $_escape = function($str) {
        return preg_replace("!([\b\t\n\r\f\"])!", "\\\\\\1", $str);
    };
    $indentWith = "    ";

    $out = '';

    foreach($in as $key=>$value) {
        $out .= str_repeat($indentWith, $indent + 1);
        $out .= "\"" . $_escape((string)$key)."\": ";

        if(is_object($value) || is_array($value)) {
            $out .= "\n";
            $out .= $_myself($value, $indent+1);
        } elseif(is_null($value)) {
            $out .= 'null';
        } elseif(is_string($value)) {
            $out .= "\"".$_escape($value) . "\"";
        } else {
            $out .= $value;
        }

        $out.= ",\n";
    }

    if(!empty($out)) {
        $out = substr($out, 0, -2);
    }

    $out = str_repeat($indentWith, $indent) . "{\n" . $out;
    $out .= "\n" . str_repeat($indentWith, $indent) . "}";

    return $out;
}

class Translation {
	private $filePath;
	private $messages;

	public function __construct($filePath) {
		if(!file_exists($filePath) || !is_readable($filePath)) {
			throw new Exception('File doesn\'t exist or is unreadable.');
		}

		$this->messages = array();
		$this->filePath = $filePath;
		$this->readJSON( json_decode( file_get_contents($filePath) ) );
	}

	public function readJSON($json) {
		if($json === NULL) {
			throw new Exception('JSON cannot be decoded.');
		}

		foreach($json as $key => $jsonObj) {
			$messageObj = array();
			$messageObj['message'] = $jsonObj->message;
			if(isset($jsonObj->description)) {
				$messageObj['description'] = $jsonObj->description;
			}

			if($this->hasMessage($key)) {
				throw new Exception('Duplicated translation key: ' . $key);
			}

			$this->messages[$key] = $messageObj;
		}
	}

	public function hasMessage($key) {
		return isset($this->messages[$key]) && !empty($this->messages[$key]['message']);
	}

	public function getMessage($key) {
		return isset($this->messages[$key]) ? $this->messages[$key] : NULL;
	}

	public function getMessages() {
		return $this->messages;
	}

	public function merge(Translation $baseTranslation) {
		$newMessages = array();
		$missing = 0;

		$baseMessages = $baseTranslation->getMessages();

		foreach($baseMessages as $key => $messageObj) {
			if($this->hasMessage($key)) {
				$newMessages[$key] = $this->getMessage($key);
			} else {
				$missing++;
				$newMessages[$key] = $messageObj;
			}
		}

		$this->messages = $newMessages;

		return $missing;
	}

	public function commit() {
		if(!is_writable($this->filePath)) {
			throw new Exception('File is not writable.');
		}

		$json = json_readable_encode($this->messages);

		if($json === FALSE) {
			throw new Exception('JSON cannot be encoded.');
		}

		if(file_put_contents($this->filePath, $json) === FALSE) {
			throw new Exception('Writing into file failed.');
		}
	}
}

$baseTranslationFolder = 'en';
$baseTranslation = new Translation($baseTranslationFolder . '/messages.json');

echo 'Number of messages: ' . count($baseTranslation->getMessages()) . PHP_EOL;

$baseTranslation->commit();

$currentFolder = new DirectoryIterator(dirname(__FILE__));

foreach ($currentFolder as $subfolder) {
	if($subfolder->isDot() || !$subfolder->isDir() || $subfolder->getFilename() == $baseTranslationFolder) {
		continue;
	}

	$translation = new Translation($subfolder->getPathname() . '/messages.json');
	$missingMessages = $translation->merge($baseTranslation);
	$translation->commit();

	echo 'Folder "' . $subfolder->getFilename() . '" has ' . $missingMessages . ' untranslated messages.' . PHP_EOL;
}

================================================
FILE: _locales/de/messages.json
================================================
{
    "locale": 
    {
        "message": "en",
        "description": "There is build in @@_ui_locale variable but it shows language variations like en_GB, en_US etc. We don't want that."
    },
    "application_description": 
    {
        "message": "Sort extensions into groups and easily switch between them."
    },
    "all_extensions": 
    {
        "message": "All extensions"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "highlight ungrouped extensions"
    },
    "create_new_context": 
    {
        "message": "Create new context"
    },
    "edit_context": 
    {
        "message": "Edit context"
    },
    "name_field_is_required": 
    {
        "message": "Name field is required."
    },
    "this_name_is_already_in_use": 
    {
        "message": "This name is already in use."
    },
    "pick_an_icon": 
    {
        "message": "Pick an icon."
    },
    "available_extensions": 
    {
        "message": "Available extensions"
    },
    "always_enabled_extensions": 
    {
        "message": "Always-enabled extensions"
    },
    "name": 
    {
        "message": "Name"
    },
    "options": 
    {
        "message": "Options"
    },
    "icon": 
    {
        "message": "Icon"
    },
    "context_will_be_deleted": 
    {
        "message": "Context will be deleted. Are you sure?"
    },
    "additional_options": 
    {
        "message": "Additional options"
    },
    "new_context": 
    {
        "message": "New Context"
    },
    "save": 
    {
        "message": "Save"
    },
    "about": 
    {
        "message": "About"
    },
    "configuration_import_export": 
    {
        "message": "Configuration import/export"
    },
    "configuration_import": 
    {
        "message": "Configuration import"
    },
    "configuration_export_description": 
    {
        "message": "To export all your settings, copy encoded configuration string from the box below."
    },
    "configuration_import_description": 
    {
        "message": "Paste configuration string to the box below and click 'Import' to restore your configuration."
    },
    "confirm_configuration_import": 
    {
        "message": "Import will override your current configuration, be sure to make a backup if you don't want to lose it."
    },
    "import": 
    {
        "message": "Import"
    },
    "override_current_settings": 
    {
        "message": "Override current settings?"
    },
    "import_failed": 
    {
        "message": "Import failed"
    },
    "configuration_string_is_invalid": 
    {
        "message": "Sorry, provided configuration string is invalid. Import failed."
    },
    "successful_import": 
    {
        "message": "Successful import"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "Configuration was imported successfuly."
    },
    "some_extensions_were_ignored": 
    {
        "message": "Some extensions from imported configuration were ignored because they are not installed:"
    },
    "override_server_settings": 
    {
        "message": "Override configuration on server?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "This will override your current configuration kept in Chrome Sync. Do you want to proceed?"
    },
    "manual": 
    {
        "message": "Manual"
    },
    "chrome_sync": 
    {
        "message": "Chrome Sync"
    },
    "save_on_server": 
    {
        "message": "Save on server"
    },
    "load_from_server": 
    {
        "message": "Load from server"
    },
    "saved": 
    {
        "message": "Saved"
    },
    "enable_apps_support": 
    {
        "message": "enable apps support (by default only extensions are supported)"
    },
    "show_all_extensions_button": 
    {
        "message": "show 'All extensions' button in popup"
    },
    "delay_after_enabling_extension": 
    {
        "message": "delay in milliseconds after enabling each extension"
    },
    "context_options": 
    {
        "message": "Context - Options"
    },
    "remove_context": 
    {
        "message": "Remove context?"
    },
    "cancel": 
    {
        "message": "Cancel"
    },
    "edit": 
    {
        "message": "Edit"
    },
    "create": 
    {
        "message": "Create"
    },
    "delete": 
    {
        "message": "Delete"
    },
    "clone": 
    {
        "message": "Clone"
    },
    "move": 
    {
        "message": "Move"
    },
    "extension_is_loading": 
    {
        "message": "Extension is loading ..."
    },
    "new_extension_installed_action": 
    {
        "message": "after new extension is installed"
    },
    "ask_what_to_do": 
    {
        "message": "ask what to do"
    },
    "add_to_all_contexts": 
    {
        "message": "add extension to all contexts"
    },
    "add_to_always_enabled": 
    {
        "message": "add to 'always-enabled'"
    },
    "do_nothing": 
    {
        "message": "do nothing"
    },
    "extension_installed_1": 
    {
        "message": "New extension"
    },
    "extension_installed_2": 
    {
        "message": "installed"
    },
    "add_to_contexts": 
    {
        "message": "Add it to the following contexts"
    },
    "or_add_it_to": 
    {
        "message": "or add it to"
    },
    "font": 
    {
        "message": "Font"
    },
    "icons": 
    {
        "message": "Icons"
    },
    "icon_flip_animation": 
    {
        "message": "Icon flip animation"
    },
    "programmer": 
    {
        "message": "Programmer"
    },
    "source_code": 
    {
        "message": "Source code"
    },
    "translations": 
    {
        "message": "Translations"
    },
    "welcome": 
    {
        "message": "Welcome"
    },
    "welcome_step_1": 
    {
        "message": "Welcome! To start working with this extension, create contexts (extension groups). For each context choose a name and an icon."
    },
    "welcome_step_2": 
    {
        "message": "To connect extensions with contexts, drag them from top alphabetical list to a chosen box representing context."
    },
    "welcome_step_3": 
    {
        "message": "Move all extensions that should be enabled for every context from 'Available extensions' box to 'Always-enabled extensions' box."
    },
    "welcome_step_4": 
    {
        "message": "Save your configuration and you are done! You can easily switch between contexts using icon in the toolbar. Selecting context name or icon on the menu switches to selected context. Clicking on plus/minus button activates/deactivates chosen context allowing you to mix contexts with each other."
    },
    "next": 
    {
        "message": "Next"
    },
    "previous": 
    {
        "message": "Previous"
    },
    "close": 
    {
        "message": "Close"
    },
    "show_extension_icon": 
    {
        "message": "In the popup use icon of the first extension instead of the context icon."
    },
    "open_notification": 
    {
        "message": "Click here to decide what contexts you want to add it to."
    }
}

================================================
FILE: _locales/en/messages.json
================================================
{
    "locale": 
    {
        "message": "en",
        "description": "There is build in @@_ui_locale variable but it shows language variations like en_GB, en_US etc. We don't want that."
    },
    "application_description": 
    {
        "message": "Sort extensions into groups and easily switch between them."
    },
    "all_extensions": 
    {
        "message": "All extensions"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "highlight ungrouped extensions"
    },
    "create_new_context": 
    {
        "message": "Create new context"
    },
    "edit_context": 
    {
        "message": "Edit context"
    },
    "name_field_is_required": 
    {
        "message": "Name field is required."
    },
    "this_name_is_already_in_use": 
    {
        "message": "This name is already in use."
    },
    "pick_an_icon": 
    {
        "message": "Pick an icon."
    },
    "available_extensions": 
    {
        "message": "Available extensions"
    },
    "always_enabled_extensions": 
    {
        "message": "Always-enabled extensions"
    },
    "name": 
    {
        "message": "Name"
    },
    "options": 
    {
        "message": "Options"
    },
    "icon": 
    {
        "message": "Icon"
    },
    "context_will_be_deleted": 
    {
        "message": "Context will be deleted. Are you sure?"
    },
    "additional_options": 
    {
        "message": "Additional options"
    },
    "new_context": 
    {
        "message": "New Context"
    },
    "save": 
    {
        "message": "Save"
    },
    "about": 
    {
        "message": "About"
    },
    "configuration_import_export": 
    {
        "message": "Configuration import/export/sync"
    },
    "configuration_import": 
    {
        "message": "Configuration import"
    },
    "configuration_export_description": 
    {
        "message": "To export all your settings, copy encoded configuration string from the box below."
    },
    "configuration_import_description": 
    {
        "message": "Paste configuration string to the box below and click 'Import' to restore your configuration."
    },
    "confirm_configuration_import": 
    {
        "message": "Import will override your current configuration, be sure to make a backup if you don't want to lose it."
    },
    "import": 
    {
        "message": "Import"
    },
    "override_current_settings": 
    {
        "message": "Override current settings?"
    },
    "import_failed": 
    {
        "message": "Import failed"
    },
    "configuration_string_is_invalid": 
    {
        "message": "Sorry, provided configuration string is invalid. Import failed."
    },
    "successful_import": 
    {
        "message": "Successful import"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "Configuration was imported successfully."
    },
    "some_extensions_were_ignored": 
    {
        "message": "Some extensions from imported configuration were ignored because they are not installed:"
    },
    "override_server_settings": 
    {
        "message": "Override configuration on server?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "This will override your current configuration kept in Chrome Sync. Do you want to proceed?"
    },
    "manual": 
    {
        "message": "Manual"
    },
    "chrome_sync": 
    {
        "message": "Chrome Sync"
    },
    "save_on_server": 
    {
        "message": "Save on server"
    },
    "load_from_server": 
    {
        "message": "Load from server"
    },
    "saved": 
    {
        "message": "Saved"
    },
    "enable_apps_support": 
    {
        "message": "enable apps support (by default only extensions are supported)"
    },
    "show_all_extensions_button": 
    {
        "message": "show 'All extensions' button in popup"
    },
    "delay_after_enabling_extension": 
    {
        "message": "delay in milliseconds after enabling each extension"
    },
    "context_options": 
    {
        "message": "Context - Options"
    },
    "remove_context": 
    {
        "message": "Remove context?"
    },
    "cancel": 
    {
        "message": "Cancel"
    },
    "edit": 
    {
        "message": "Edit"
    },
    "create": 
    {
        "message": "Create"
    },
    "delete": 
    {
        "message": "Delete"
    },
    "clone": 
    {
        "message": "Clone"
    },
    "move": 
    {
        "message": "Move"
    },
    "extension_is_loading": 
    {
        "message": "Extension is loading ..."
    },
    "new_extension_installed_action": 
    {
        "message": "after new extension is installed"
    },
    "ask_what_to_do": 
    {
        "message": "ask what to do"
    },
    "add_to_all_contexts": 
    {
        "message": "add extension to all contexts"
    },
    "add_to_always_enabled": 
    {
        "message": "add to 'always-enabled'"
    },
    "do_nothing": 
    {
        "message": "do nothing"
    },
    "extension_installed_1": 
    {
        "message": "New extension"
    },
    "extension_installed_2": 
    {
        "message": "installed"
    },
    "add_to_contexts": 
    {
        "message": "Add it to the following contexts"
    },
    "or_add_it_to": 
    {
        "message": "or add it to"
    },
    "font": 
    {
        "message": "Font"
    },
    "icons": 
    {
        "message": "Icons"
    },
    "icon_flip_animation": 
    {
        "message": "Icon flip animation"
    },
    "programmer": 
    {
        "message": "Programmer"
    },
    "source_code": 
    {
        "message": "Source code"
    },
    "translations": 
    {
        "message": "Translations"
    },
    "welcome": 
    {
        "message": "Welcome"
    },
    "welcome_step_1": 
    {
        "message": "Welcome! To start working with this extension, create contexts (extension groups). For each context choose a name and an icon."
    },
    "welcome_step_2": 
    {
        "message": "To connect extensions with contexts, drag them from top alphabetical list to a chosen box representing context."
    },
    "welcome_step_3": 
    {
        "message": "Move all extensions that should be enabled for every context from 'Available extensions' box to 'Always-enabled extensions' box."
    },
    "welcome_step_4": 
    {
        "message": "Save your configuration and you are done! You can easily switch between contexts using icon in the toolbar. Selecting context name or icon on the menu switches to selected context. Clicking on plus/minus button activates/deactivates chosen context allowing you to mix contexts with each other."
    },
    "next": 
    {
        "message": "Next"
    },
    "previous": 
    {
        "message": "Previous"
    },
    "close": 
    {
        "message": "Close"
    },
    "show_extension_icon": 
    {
        "message": "In the popup use icon of the first extension instead of the context icon."
    },
    "open_notification": 
    {
        "message": "Click here to decide what contexts you want to add it to."
    }
}

================================================
FILE: _locales/es/messages.json
================================================
{
    "locale": 
    {
        "message": "en",
        "description": "There is build in @@_ui_locale variable but it shows language variations like en_GB, en_US etc. We don't want that."
    },
    "application_description": 
    {
        "message": "Extensiones para clasificar en grupos y cambiar fácilmente entre ellas."
    },
    "all_extensions": 
    {
        "message": "Todas las extensiones"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "highlight ungrouped extensions"
    },
    "create_new_context": 
    {
        "message": "Crear nuevo grupo"
    },
    "edit_context": 
    {
        "message": "Editar grupo"
    },
    "name_field_is_required": 
    {
        "message": "Campo nombre es obligatorio."
    },
    "this_name_is_already_in_use": 
    {
        "message": "Este nombre ya está en uso."
    },
    "pick_an_icon": 
    {
        "message": "Elige un icono."
    },
    "available_extensions": 
    {
        "message": "Extensiones disponibles"
    },
    "always_enabled_extensions": 
    {
        "message": "Extensiones siempre activadas"
    },
    "name": 
    {
        "message": "Nombre"
    },
    "options": 
    {
        "message": "Opciones"
    },
    "icon": 
    {
        "message": "Icono"
    },
    "context_will_be_deleted": 
    {
        "message": "Los grupos serán borrados. ¿Está seguro?"
    },
    "additional_options": 
    {
        "message": "Opciones adicionales"
    },
    "new_context": 
    {
        "message": "Nuevo grupo"
    },
    "save": 
    {
        "message": "Guardar"
    },
    "about": 
    {
        "message": "Sobre"
    },
    "configuration_import_export": 
    {
        "message": "Configuration import/export"
    },
    "configuration_import": 
    {
        "message": "Configuration import"
    },
    "configuration_export_description": 
    {
        "message": "To export all your settings, copy encoded configuration string from the box below."
    },
    "configuration_import_description": 
    {
        "message": "Paste configuration string to the box below and click 'Import' to restore your configuration."
    },
    "confirm_configuration_import": 
    {
        "message": "Import will override your current configuration, be sure to make a backup if you don't want to lose it."
    },
    "import": 
    {
        "message": "Import"
    },
    "override_current_settings": 
    {
        "message": "Override current settings?"
    },
    "import_failed": 
    {
        "message": "Import failed"
    },
    "configuration_string_is_invalid": 
    {
        "message": "Sorry, provided configuration string is invalid. Import failed."
    },
    "successful_import": 
    {
        "message": "Successful import"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "Configuration was imported successfuly."
    },
    "some_extensions_were_ignored": 
    {
        "message": "Some extensions from imported configuration were ignored because they are not installed:"
    },
    "override_server_settings": 
    {
        "message": "Override configuration on server?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "This will override your current configuration kept in Chrome Sync. Do you want to proceed?"
    },
    "manual": 
    {
        "message": "Manual"
    },
    "chrome_sync": 
    {
        "message": "Chrome Sync"
    },
    "save_on_server": 
    {
        "message": "Save on server"
    },
    "load_from_server": 
    {
        "message": "Load from server"
    },
    "saved": 
    {
        "message": "Saved"
    },
    "enable_apps_support": 
    {
        "message": "habilitar soporte de aplicaciones (por defecto, sólo las extensiones son compatibles)"
    },
    "show_all_extensions_button": 
    {
        "message": "Mostrar el botón 'Todas las extensiones' en popup"
    },
    "delay_after_enabling_extension": 
    {
        "message": "delay in milliseconds after enabling each extension"
    },
    "context_options": 
    {
        "message": "Grupo - Opciones"
    },
    "remove_context": 
    {
        "message": "Quitar grupo?"
    },
    "cancel": 
    {
        "message": "Cancelar"
    },
    "edit": 
    {
        "message": "Editar"
    },
    "create": 
    {
        "message": "Crear"
    },
    "delete": 
    {
        "message": "Borrar"
    },
    "clone": 
    {
        "message": "Duplicar"
    },
    "move": 
    {
        "message": "Mover"
    },
    "extension_is_loading": 
    {
        "message": "La extensión se está cargando ..."
    },
    "new_extension_installed_action": 
    {
        "message": "Después de que el grupo se instale"
    },
    "ask_what_to_do": 
    {
        "message": "preguntarle qué hacer"
    },
    "add_to_all_contexts": 
    {
        "message": "DAña extensión a todos los grupos"
    },
    "add_to_always_enabled": 
    {
        "message": "add to 'always-enabled'"
    },
    "do_nothing": 
    {
        "message": "no hacer nada"
    },
    "extension_installed_1": 
    {
        "message": "Nuevo grupo"
    },
    "extension_installed_2": 
    {
        "message": "instalado"
    },
    "add_to_contexts": 
    {
        "message": "Añadir a los siguientes grupos"
    },
    "or_add_it_to": 
    {
        "message": "or add it to"
    },
    "font": 
    {
        "message": "Fuente"
    },
    "icons": 
    {
        "message": "Iconos"
    },
    "icon_flip_animation": 
    {
        "message": "Animación del icono"
    },
    "programmer": 
    {
        "message": "Programador"
    },
    "source_code": 
    {
        "message": "Source code"
    },
    "translations": 
    {
        "message": "Traducciones"
    },
    "welcome": 
    {
        "message": "Bienvenido"
    },
    "welcome_step_1": 
    {
        "message": "Bienvenido! Puedes empezar a trabajar con esta extensión de crear grupos (grupos de extensiones). Para cada grupo elegir un nombre y un icono."
    },
    "welcome_step_2": 
    {
        "message": "Para conectar las extensiones de los mismos grupos hay que arrastrarlas desde la lista de arriba, por orden alfabético a una caja de elegidos que representan a su grupo."
    },
    "welcome_step_3": 
    {
        "message": "Mueve todas las extensiones que deberían estar activadas para cada contexto desde 'extensiones disponibles' a la caja 'extensiones siempre disponibles'."
    },
    "welcome_step_4": 
    {
        "message": "Guarda tu configuración y listo. Puede fácilmente alternar los contextos usando los iconos en la barra de tareas. Seleccionando el nombre del contexto o el icono en el menú, cambiar al contexto seleccionado. Pulsando en el botón más/menos activa/desactiva el contexto elegido permitiendo mezclar unos contextos con otros."
    },
    "next": 
    {
        "message": "Próximo"
    },
    "previous": 
    {
        "message": "Anterior"
    },
    "close": 
    {
        "message": "Cerrar"
    },
    "show_extension_icon": 
    {
        "message": "In the popup use icon of the first extension instead of the context icon."
    },
    "open_notification": 
    {
        "message": "Click here to decide what contexts you want to add it to."
    }
}

================================================
FILE: _locales/fr/messages.json
================================================
{
    "locale": 
    {
        "message": "en",
        "description": "There is build in @@_ui_locale variable but it shows language variations like en_GB, en_US etc. We don't want that."
    },
    "application_description": 
    {
        "message": "Organisez vos extensions dans des groupes et basculez facilement entre eux."
    },
    "all_extensions": 
    {
        "message": "Toutes les extensions"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "Mettre en évidence les extensions non groupées"
    },
    "create_new_context": 
    {
        "message": "Créer un nouveau context"
    },
    "edit_context": 
    {
        "message": "Editer le context"
    },
    "name_field_is_required": 
    {
        "message": "Le champ Nom est obligatoire."
    },
    "this_name_is_already_in_use": 
    {
        "message": "Ce nom est déjà utilisé."
    },
    "pick_an_icon": 
    {
        "message": "Choisissez une icône."
    },
    "available_extensions": 
    {
        "message": "Extensions disponibles"
    },
    "always_enabled_extensions": 
    {
        "message": "Extensions toujours activées"
    },
    "name": 
    {
        "message": "Nom"
    },
    "options": 
    {
        "message": "Options"
    },
    "icon": 
    {
        "message": "Icône"
    },
    "context_will_be_deleted": 
    {
        "message": "Ce context sera supprimé. Êtes-vous sûr ?"
    },
    "additional_options": 
    {
        "message": "Options supplémentaires"
    },
    "new_context": 
    {
        "message": "Nouveau Context"
    },
    "save": 
    {
        "message": "Sauvegarder"
    },
    "about": 
    {
        "message": "À propos"
    },
    "configuration_import_export": 
    {
        "message": "Import/Export de la configuration"
    },
    "configuration_import": 
    {
        "message": "Importer la configuration"
    },
    "configuration_export_description": 
    {
        "message": "Pour exporter tous vos paramètres, copiez la chaîne de configuration codée à partir de la boîte ci-dessous."
    },
    "configuration_import_description": 
    {
        "message": "Collez la chaîne de configuration dans la boîte ci-dessous et cliquez sur \"Importer\" pour restaurer votre configuration."
    },
    "confirm_configuration_import": 
    {
        "message": "L'importation remplacera votre configuration actuelle. Pensez à faire une sauvegarde si vous ne voulez pas la perdre."
    },
    "import": 
    {
        "message": "Importer"
    },
    "override_current_settings": 
    {
        "message": "Remplacer les paramètres actuels ?"
    },
    "import_failed": 
    {
        "message": "Échec de l'importation"
    },
    "configuration_string_is_invalid": 
    {
        "message": "Désolé, la chaîne de configuration fournie n'est pas valide. Échec de l'importation."
    },
    "successful_import": 
    {
        "message": "Importation réussie"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "La configuration a été importée avec succès."
    },
    "some_extensions_were_ignored": 
    {
        "message": "Certaines extensions ont été ignorées lors de l'importation de la configuration, car elles ne sont pas installées:"
    },
    "override_server_settings": 
    {
        "message": "Override configuration on server?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "This will override your current configuration kept in Chrome Sync. Do you want to proceed?"
    },
    "manual": 
    {
        "message": "Manual"
    },
    "chrome_sync": 
    {
        "message": "Chrome Sync"
    },
    "save_on_server": 
    {
        "message": "Save on server"
    },
    "load_from_server": 
    {
        "message": "Load from server"
    },
    "saved": 
    {
        "message": "Saved"
    },
    "enable_apps_support": 
    {
        "message": "Activer le support des applications (par défaut, seules les extensions sont supportées)"
    },
    "show_all_extensions_button": 
    {
        "message": "Afficher le bouton ‘Toutes les extensions’ dans le popup"
    },
    "delay_after_enabling_extension": 
    {
        "message": "délai en millisecondes après l'activation de chaque extension"
    },
    "context_options": 
    {
        "message": "Context - Options"
    },
    "remove_context": 
    {
        "message": "Supprimer le context ?"
    },
    "cancel": 
    {
        "message": "Annuler"
    },
    "edit": 
    {
        "message": "Editer"
    },
    "create": 
    {
        "message": "Créer"
    },
    "delete": 
    {
        "message": "Supprimer"
    },
    "clone": 
    {
        "message": "Dupliquer"
    },
    "move": 
    {
        "message": "Déplacer"
    },
    "extension_is_loading": 
    {
        "message": "Chargement de l’extension..."
    },
    "new_extension_installed_action": 
    {
        "message": "après l’installation d’une nouvelle extension"
    },
    "ask_what_to_do": 
    {
        "message": "demander ce qu'il faut faire"
    },
    "add_to_all_contexts": 
    {
        "message": "ajouter l'extension à tous les contexts"
    },
    "add_to_always_enabled": 
    {
        "message": "ajouter à ‘toujours activées’"
    },
    "do_nothing": 
    {
        "message": "ne rien faire"
    },
    "extension_installed_1": 
    {
        "message": "Nouvelle extension"
    },
    "extension_installed_2": 
    {
        "message": "installée"
    },
    "add_to_contexts": 
    {
        "message": "Ajoutez-la aux contexts suivants"
    },
    "or_add_it_to": 
    {
        "message": "ou ajoutez-la à"
    },
    "font": 
    {
        "message": "Police"
    },
    "icons": 
    {
        "message": "Icônes"
    },
    "icon_flip_animation": 
    {
        "message": "Icône de rotation animée"
    },
    "programmer": 
    {
        "message": "Programmeur"
    },
    "source_code": 
    {
        "message": "Code source"
    },
    "translations": 
    {
        "message": "Traductions"
    },
    "welcome": 
    {
        "message": "Bienvenue"
    },
    "welcome_step_1": 
    {
        "message": "Bienvenue ! Pour commencer à travailler avec cette extension, créez des contexts (groupes d'extensions). Pour chaque context, choisissez un nom et une icône."
    },
    "welcome_step_2": 
    {
        "message": "Pour connecter des extensions aux différents contexts, glissez-les depuis la liste alphabétique supérieure jusqu'à la boîte représentant le context de votre choix."
    },
    "welcome_step_3": 
    {
        "message": "Déplacez, de la boîte ‘Extensions disponibles’ à la boîte ‘Extensions toujours activées’, les extensions que vous souhaitez activer dans tous les contexts."
    },
    "welcome_step_4": 
    {
        "message": "Sauvegardez votre configuration et vous avez terminé ! Vous pouvez facilement basculer d'un context à un autre en utilisant l'icône dans la barre d'outils. La sélection d'un context s'effectue en cliquant sur son nom ou son icône dans le menu. Un clic sur le bouton plus/moins (activer/désactiver) permet de mélanger les contexts entre eux."
    },
    "next": 
    {
        "message": "Suivant"
    },
    "previous": 
    {
        "message": "Précédent"
    },
    "close": 
    {
        "message": "Fermer"
    },
    "show_extension_icon": 
    {
        "message": "In the popup use icon of the first extension instead of the context icon."
    },
    "open_notification": 
    {
        "message": "Click here to decide what contexts you want to add it to."
    }
}

================================================
FILE: _locales/it/description.txt
================================================
Dai un'occhiata alle tue estensioni. Davvero le usi tutte quante e per tutto il tempo? Non credo. Lo sai che queste estensioni non utilizzate sottraggono risorse e spazio? Inoltre possono distrarti con animazioni e notifiche. Con Context puoi porre fine a tutto ciò. Ti basta mettere le estensioni che usi per lavoro, divertimento, shopping, socializzazione, ecc. in gruppi ("contesti") differenti e con un solo click passare da un gruppo all'altro.

Extra:
- puoi miscelare i contesti tra di loro usando i pulsanti +/-
- quando vengono installate nuove estensioni, Context ti permetterà di assegnarle ai gruppi più appropriati, tramite finestra di notifica - senza la necessità di aprire la pagina di configurazione
- gruppi differenti - temi differenti (supporto limitato - Chrome memorizza solo gli ultimi 3 temi)
- tutorial passo-passo al primo avvio


================================================
FILE: _locales/it/messages.json
================================================
{
    "locale": 
    {
        "message": "en",
        "description": "There is build in @@_ui_locale variable but it shows language variations like en_GB, en_US etc. We don't want that."
    },
    "application_description": 
    {
        "message": "Ordina le estensioni in gruppi e gestiscili facilmente."
    },
    "all_extensions": 
    {
        "message": "Tutte le estensioni"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "evidenzia estensioni non raggruppate"
    },
    "create_new_context": 
    {
        "message": "Crea nuovo contesto"
    },
    "edit_context": 
    {
        "message": "Modifica contesto"
    },
    "name_field_is_required": 
    {
        "message": "Il campo nome è richiesto."
    },
    "this_name_is_already_in_use": 
    {
        "message": "Questo nome è già in uso."
    },
    "pick_an_icon": 
    {
        "message": "Seleziona un'icona."
    },
    "available_extensions": 
    {
        "message": "Estensioni disponibili"
    },
    "always_enabled_extensions": 
    {
        "message": "Estensioni sempre abilitate"
    },
    "name": 
    {
        "message": "Nome"
    },
    "options": 
    {
        "message": "Opzioni"
    },
    "icon": 
    {
        "message": "Icona"
    },
    "context_will_be_deleted": 
    {
        "message": "Il contesto verrà eliminato. Sei sicuro?"
    },
    "additional_options": 
    {
        "message": "Opzioni aggiuntive"
    },
    "new_context": 
    {
        "message": "Nuovo contesto"
    },
    "save": 
    {
        "message": "Salva"
    },
    "about": 
    {
        "message": "Informazioni"
    },
    "configuration_import_export": 
    {
        "message": "Importa/esporta configurazione"
    },
    "configuration_import": 
    {
        "message": "Importa configurazione"
    },
    "configuration_export_description": 
    {
        "message": "Per esportare tutte le tue impostazioni, copia la stringa di configurazione codificata dal riquadro sottostante."
    },
    "configuration_import_description": 
    {
        "message": "Incolla la stringa di configurazione nel riquadro sottostante e clicca 'Importa' per ripristinare la tua configurazione."
    },
    "confirm_configuration_import": 
    {
        "message": "L'importazione sovrascriverà l'attuale configurazione, assicurati di fare una copia di sicurezza se non vuoi perderla."
    },
    "import": 
    {
        "message": "Importa"
    },
    "override_current_settings": 
    {
        "message": "Sovrascrivere le impostazioni attuali?"
    },
    "import_failed": 
    {
        "message": "Importazione fallita"
    },
    "configuration_string_is_invalid": 
    {
        "message": "Spiacente, la stringa di configurazione fornita non è valida. Importazione fallita."
    },
    "successful_import": 
    {
        "message": "Importazione terminata"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "La configurazione è stata importata con successo."
    },
    "some_extensions_were_ignored": 
    {
        "message": "Alcune estensioni presenti nella configurazione importata sono state ignorate perché non sono installate:"
    },
    "override_server_settings": 
    {
        "message": "Sovrascrivere la configurazione sul server?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "Questo sovrascriverà l'attuale configurazione sincronizzata in Chrome. Vuoi continuare?"
    },
    "manual": 
    {
        "message": "Manuale"
    },
    "chrome_sync": 
    {
        "message": "Sincronizza in Chrome"
    },
    "save_on_server": 
    {
        "message": "Salva sul server"
    },
    "load_from_server": 
    {
        "message": "Carica dal server"
    },
    "saved": 
    {
        "message": "Salvato"
    },
    "enable_apps_support": 
    {
        "message": "abilita supporto alle app (di default sono supportate solo le estensioni)"
    },
    "show_all_extensions_button": 
    {
        "message": "mostra il pulsante 'Tutte le estensioni' nel popup"
    },
    "delay_after_enabling_extension": 
    {
        "message": "ritardo in millisecondi dopo l'abilitazione di ogni estensione"
    },
    "context_options": 
    {
        "message": "Context - Opzioni"
    },
    "remove_context": 
    {
        "message": "Rimuovere contesto?"
    },
    "cancel": 
    {
        "message": "Annulla"
    },
    "edit": 
    {
        "message": "Modifica"
    },
    "create": 
    {
        "message": "Crea"
    },
    "delete": 
    {
        "message": "Elimina"
    },
    "clone": 
    {
        "message": "Duplica"
    },
    "move": 
    {
        "message": "Sposta"
    },
    "extension_is_loading": 
    {
        "message": "Estensione in caricamento ..."
    },
    "new_extension_installed_action": 
    {
        "message": "dopo che la nuova estensione viene installata"
    },
    "ask_what_to_do": 
    {
        "message": "chiedi cosa fare"
    },
    "add_to_all_contexts": 
    {
        "message": "aggiungi estensione a tutti i contesti"
    },
    "add_to_always_enabled": 
    {
        "message": "aggiungi a 'sempre abilitate'"
    },
    "do_nothing": 
    {
        "message": "non fare nulla"
    },
    "extension_installed_1": 
    {
        "message": "Nuova estensione"
    },
    "extension_installed_2": 
    {
        "message": "installata"
    },
    "add_to_contexts": 
    {
        "message": "Aggiungila ai seguenti contesti"
    },
    "or_add_it_to": 
    {
        "message": "o aggiungila a"
    },
    "font": 
    {
        "message": "Font"
    },
    "icons": 
    {
        "message": "Icone"
    },
    "icon_flip_animation": 
    {
        "message": "Animazione icona"
    },
    "programmer": 
    {
        "message": "Programmatore"
    },
    "source_code": 
    {
        "message": "Codice sorgente"
    },
    "translations": 
    {
        "message": "Traduzioni"
    },
    "welcome": 
    {
        "message": "Benvenuto"
    },
    "welcome_step_1": 
    {
        "message": "Benvenuto! Per iniziare ad usare questa estensione, crea dei contesti (gruppi estensione). Per ogni contesto scegli un nome ed un'icona."
    },
    "welcome_step_2": 
    {
        "message": "Per connettere le estensioni ai contesti, trascinale dall'elenco alfabetico in alto, ad un riquadro rappresentante un contesto."
    },
    "welcome_step_3": 
    {
        "message": "Sposta tutte le estensioni che dovrebbero essere abilitate per ogni contesto, dal riquadro 'Estensioni disponibili' al riquadro 'Estensioni sempre abilitate'."
    },
    "welcome_step_4": 
    {
        "message": "Salva la tua configurazione e sei pronto! Puoi facilmente passare tra i contesti usando l'icona nella barra strumenti. Seleziona il nome del contesto o l'icona nel menu per passare al contesto selezionato. Clicca il pulsante più/meno per attivare/disattivare il contesto scelto così da poter miscelare i contesti tra di loro."
    },
    "next": 
    {
        "message": "Avanti"
    },
    "previous": 
    {
        "message": "Indietro"
    },
    "close": 
    {
        "message": "Chiudi"
    },
    "show_extension_icon": 
    {
        "message": "Nel popup, invece dell'icona del contesto, usa quella della prima estensione."
    },
    "open_notification": 
    {
        "message": "Click here to decide what contexts you want to add it to."
    }
}

================================================
FILE: _locales/ja/messages.json
================================================
{
    "locale": 
    {
        "message": "en",
        "description": "There is build in @@_ui_locale variable but it shows language variations like en_GB, en_US etc. We don't want that."
    },
    "application_description": 
    {
        "message": "Chrome拡張機能をグループ化し、用途によってカンタンに切り替えられます。"
    },
    "all_extensions": 
    {
        "message": "すべての拡張機能"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "グループに追加されていない拡張機能をハイライト表示する"
    },
    "create_new_context": 
    {
        "message": "新しいグループを作成"
    },
    "edit_context": 
    {
        "message": "グループを編集"
    },
    "name_field_is_required": 
    {
        "message": "グループ名の入力は必須です。"
    },
    "this_name_is_already_in_use": 
    {
        "message": "この名前はすでに使用されています。"
    },
    "pick_an_icon": 
    {
        "message": "アイコンを選んで下さい。"
    },
    "available_extensions": 
    {
        "message": "利用可能な拡張機能"
    },
    "always_enabled_extensions": 
    {
        "message": "常時有効にする拡張機能"
    },
    "name": 
    {
        "message": "グループ名"
    },
    "options": 
    {
        "message": "オプション"
    },
    "icon": 
    {
        "message": "アイコン"
    },
    "context_will_be_deleted": 
    {
        "message": "Contextが消去されます。よろしいですか?"
    },
    "additional_options": 
    {
        "message": "追加オプション"
    },
    "new_context": 
    {
        "message": "新しいグループ"
    },
    "save": 
    {
        "message": "保存"
    },
    "about": 
    {
        "message": "Contextについて"
    },
    "configuration_import_export": 
    {
        "message": "設定のインポート/エクスポート"
    },
    "configuration_import": 
    {
        "message": "設定のインポート"
    },
    "configuration_export_description": 
    {
        "message": "設定をすべてエクスポートするには、下記ボックスに表示されるエンコードされた文字列をコピーします。"
    },
    "configuration_import_description": 
    {
        "message": "設定の文字列を下記ボックスに貼り付け、「インポート」をクリックすると設定が反映されます。"
    },
    "confirm_configuration_import": 
    {
        "message": "インポートすると現在の設定が無効になります。現在の設定を残しておきたい場合はバックアップを取っておいてください。"
    },
    "import": 
    {
        "message": "インポート"
    },
    "override_current_settings": 
    {
        "message": "現在の設定を無効にしますか?"
    },
    "import_failed": 
    {
        "message": "インポートに失敗しました"
    },
    "configuration_string_is_invalid": 
    {
        "message": "ごめんなさい、いただいた設定の文字列は無効です。インポートに失敗しました。"
    },
    "successful_import": 
    {
        "message": "インポートに成功しました"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "設定のインポートに成功しました。"
    },
    "some_extensions_were_ignored": 
    {
        "message": "設定がインポートされた拡張機能のうち、いくつかはインポートが無視されました。インポートが無視された設定は、拡張機能がインストールされていないようです。:"
    },
    "override_server_settings": 
    {
        "message": "Override configuration on server?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "This will override your current configuration kept in Chrome Sync. Do you want to proceed?"
    },
    "manual": 
    {
        "message": "Manual"
    },
    "chrome_sync": 
    {
        "message": "Chrome Sync"
    },
    "save_on_server": 
    {
        "message": "Save on server"
    },
    "load_from_server": 
    {
        "message": "Load from server"
    },
    "saved": 
    {
        "message": "Saved"
    },
    "enable_apps_support": 
    {
        "message": "Chrome WEBアプリも対象にする (デフォルトは拡張機能のみ対象)"
    },
    "show_all_extensions_button": 
    {
        "message": "ポップアップメニューに「すべての拡張機能」を表示する"
    },
    "delay_after_enabling_extension": 
    {
        "message": "各拡張機能を有効にした後、数ミリ秒間遅らせる"
    },
    "context_options": 
    {
        "message": "Context - オプション"
    },
    "remove_context": 
    {
        "message": "グループを削除しますか?"
    },
    "cancel": 
    {
        "message": "キャンセル"
    },
    "edit": 
    {
        "message": "編集"
    },
    "create": 
    {
        "message": "作成"
    },
    "delete": 
    {
        "message": "削除"
    },
    "clone": 
    {
        "message": "複製する"
    },
    "move": 
    {
        "message": "移動する"
    },
    "extension_is_loading": 
    {
        "message": "拡張機能を読み込んでいます。 ..."
    },
    "new_extension_installed_action": 
    {
        "message": "新しい拡張機能をインストールした直後の動作設定"
    },
    "ask_what_to_do": 
    {
        "message": "何をしたら良いか通知する"
    },
    "add_to_all_contexts": 
    {
        "message": "この拡張機能をすべてのグループへ追加"
    },
    "add_to_always_enabled": 
    {
        "message": "「常時有効にする拡張機能」へ追加'"
    },
    "do_nothing": 
    {
        "message": "何もしない"
    },
    "extension_installed_1": 
    {
        "message": "新しい拡張機能がインストールされました"
    },
    "extension_installed_2": 
    {
        "message": "インストールされました"
    },
    "add_to_contexts": 
    {
        "message": "この拡張機能を以下のグループへ追加"
    },
    "or_add_it_to": 
    {
        "message": "または追加"
    },
    "font": 
    {
        "message": "フォント"
    },
    "icons": 
    {
        "message": "アイコン"
    },
    "icon_flip_animation": 
    {
        "message": "アイコンフリップ アニメーション"
    },
    "programmer": 
    {
        "message": "プログラマー"
    },
    "source_code": 
    {
        "message": "ソースコード"
    },
    "translations": 
    {
        "message": "翻訳"
    },
    "welcome": 
    {
        "message": "はじめに"
    },
    "welcome_step_1": 
    {
        "message": "インストールしてくれてありがとう! これからこの拡張機能で、拡張機能のグループ(コンテクスト)を作成します。いずれのグループも、作成する際に名前とアイコンを選ぶことができます。"
    },
    "welcome_step_2": 
    {
        "message": "グループを作成したら、拡張機能をグループへ追加しましょう。グループへの追加はドラッグアンドドロップでおこなえます。Google Chromeに追加されている拡張機能は、上部のボックスにアルファベット順に並んでいます。ここから下にあるグループごとのボックスへ拡張機能を追加します。"
    },
    "welcome_step_3": 
    {
        "message": "「利用可能な拡張機能」ボックスから「常時有効にする拡張機能」ボックスへ、すべての拡張機能を移動させることによって、すべてのグループで移動させた拡張機能を有効にすることができます。"
    },
    "welcome_step_4": 
    {
        "message": "設定を保存することで、ツールバーのアイコンからカンタンにグループを変更することができます。メニューボタンに表示するグループ名とアイコンを選択し、+/ーボタンを押すことで 有効/無効 を切り替えることができます。複数のグループを同時に選択することも可能です。"
    },
    "next": 
    {
        "message": "次へ"
    },
    "previous": 
    {
        "message": "前へ"
    },
    "close": 
    {
        "message": "閉じる"
    },
    "show_extension_icon": 
    {
        "message": "In the popup use icon of the first extension instead of the context icon."
    },
    "open_notification": 
    {
        "message": "Click here to decide what contexts you want to add it to."
    }
}

================================================
FILE: _locales/pl/messages.json
================================================
{
    "locale": 
    {
        "message": "pl",
        "description": "Istnieje wbudowana zmienna @@_ui_locale która zawiera tą informacje, ale jest ona zbyt dokładna jak na nasze potrzeby (en_GB, en_US)."
    },
    "application_description": 
    {
        "message": "Połącz swoje rozszerzenia w grupy i wygodnie przełączaj się między nimi."
    },
    "all_extensions": 
    {
        "message": "Wszystkie dodatki"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "podświetl niepogrupowane rozszerzenia"
    },
    "create_new_context": 
    {
        "message": "Nowy kontekst"
    },
    "edit_context": 
    {
        "message": "Edytuj kontekst"
    },
    "name_field_is_required": 
    {
        "message": "Nazwa jest wymagana."
    },
    "this_name_is_already_in_use": 
    {
        "message": "Nazwa jest już zajęta."
    },
    "pick_an_icon": 
    {
        "message": "Wybierz ikonę."
    },
    "available_extensions": 
    {
        "message": "Dostępne rozszerzenia"
    },
    "always_enabled_extensions": 
    {
        "message": "Zawsze aktywne rozszerzenia"
    },
    "name": 
    {
        "message": "Nazwa"
    },
    "options": 
    {
        "message": "Ustawienia"
    },
    "icon": 
    {
        "message": "Ikona"
    },
    "context_will_be_deleted": 
    {
        "message": "Kontekst zostanie usunięty. Kontynuować?"
    },
    "additional_options": 
    {
        "message": "Opcje dodatkowe"
    },
    "new_context": 
    {
        "message": "Nowy kontekst"
    },
    "save": 
    {
        "message": "Zapisz"
    },
    "about": 
    {
        "message": "O tym dodatku"
    },
    "configuration_import_export": 
    {
        "message": "Import/export/synchronizacja konfiguracji"
    },
    "configuration_import": 
    {
        "message": "Import konfiguracji"
    },
    "configuration_export_description": 
    {
        "message": "Aby eksportować wszystkie ustawienia, skopiuj konfigurację z poniższego pola."
    },
    "configuration_import_description": 
    {
        "message": "Aby importować ustawienia wklej konfigurację do poniższego pola a następnie kliknij 'Import'."
    },
    "confirm_configuration_import": 
    {
        "message": "Import nadpisze obecne ustawienia, jeżeli nie chcesz ich stracić pamiętaj o zrobieniu kopii zapasowej."
    },
    "import": 
    {
        "message": "Import"
    },
    "override_current_settings": 
    {
        "message": "Nadpisać obecne ustawienia?"
    },
    "import_failed": 
    {
        "message": "Import nie powiódł się"
    },
    "configuration_string_is_invalid": 
    {
        "message": "Podana konfiguracja nie jest prawidłowa, import nie powiódł się."
    },
    "successful_import": 
    {
        "message": "Import zakończony sukcesem"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "Konfiguracja została zaimportowana poprawnie."
    },
    "some_extensions_were_ignored": 
    {
        "message": "Niektóre rozszerzenia z importowanej konfiguracji zostały pominięte ponieważ nie są zainstalowane:"
    },
    "override_server_settings": 
    {
        "message": "Nadpisać konfigurację na serwerze?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "Ta akcja spowoduje nadpisanie istniejących ustawień zapisanych na serwerze. Kontynuować?"
    },
    "manual": 
    {
        "message": "Ręcznie"
    },
    "chrome_sync": 
    {
        "message": "Chrome Sync"
    },
    "save_on_server": 
    {
        "message": "Wyślij na swerwer"
    },
    "load_from_server": 
    {
        "message": "Załaduj z serwera"
    },
    "saved": 
    {
        "message": "Zapisano"
    },
    "enable_apps_support": 
    {
        "message": "włącz obsługę aplikacji (domyślnie jedynie rozszerzenia są obsługiwane)"
    },
    "show_all_extensions_button": 
    {
        "message": "pokaż przycisk 'Wszystkie dodatki' w popup'ie"
    },
    "delay_after_enabling_extension": 
    {
        "message": "opóźnienie w milisekundach po uaktywnieniu każdego rozszerzenia"
    },
    "context_options": 
    {
        "message": "Context - Ustawienia"
    },
    "remove_context": 
    {
        "message": "Usunać kontekst?"
    },
    "cancel": 
    {
        "message": "Anuluj"
    },
    "edit": 
    {
        "message": "Edytuj"
    },
    "create": 
    {
        "message": "Utwórz"
    },
    "delete": 
    {
        "message": "Usuń"
    },
    "clone": 
    {
        "message": "Duplikuj"
    },
    "move": 
    {
        "message": "Przenieś"
    },
    "extension_is_loading": 
    {
        "message": "Ładowanie rozszerzenia ..."
    },
    "new_extension_installed_action": 
    {
        "message": "po instalacji nowego rozszerzenia"
    },
    "ask_what_to_do": 
    {
        "message": "zapytaj co robić"
    },
    "add_to_all_contexts": 
    {
        "message": "dodaj do wszystkich kontekstów"
    },
    "add_to_always_enabled": 
    {
        "message": "dodaj do 'zawsze aktywnych'"
    },
    "do_nothing": 
    {
        "message": "nie rób nic"
    },
    "extension_installed_1": 
    {
        "message": "Nowe rozszerzenie"
    },
    "extension_installed_2": 
    {
        "message": "zostało zainstalowane"
    },
    "add_to_contexts": 
    {
        "message": "Dodaj je do wybranych kontekstów"
    },
    "or_add_it_to": 
    {
        "message": "lub dodaj do"
    },
    "font": 
    {
        "message": "Czcionka"
    },
    "icons": 
    {
        "message": "Ikony"
    },
    "icon_flip_animation": 
    {
        "message": "Animacja obrotu ikony"
    },
    "programmer": 
    {
        "message": "Programista"
    },
    "source_code": 
    {
        "message": "Kod źródłowy"
    },
    "translations": 
    {
        "message": "Tłumaczenia"
    },
    "welcome": 
    {
        "message": "Witaj"
    },
    "welcome_step_1": 
    {
        "message": "Witaj! Pracę z tym dodatkiem zacznij od stworzenia kontekstów (grup dodatków). Dla każdego z kontekstów wybierz nazwę i ikonę."
    },
    "welcome_step_2": 
    {
        "message": "Aby dodać dodatki do kontekstów przeciągnij je z górnej, alfabetycznej listy do wybranego boksu reprezentującego kontekst."
    },
    "welcome_step_3": 
    {
        "message": "Przenieś dodatki które powinny być aktywne dla każdego z kontekstów z boksu 'Dostępne rozszerzenia' do boksu 'Zawsze aktywne rozszerzenia'."
    },
    "welcome_step_4": 
    {
        "message": "Zapisz ustawienia i gotowe! Możesz łatwo przełączać się pomiędzy kontekstami za pomocą ikony w pasku Twojej przeglądarki. Wybranie nazwy z menu przełącza do danego kontekstu. Wybranie przycisku plusa/minusa powoduje aktywację/dezaktywację kontekstu co pozwala na łączenie kontekstów ze sobą."
    },
    "next": 
    {
        "message": "Dalej"
    },
    "previous": 
    {
        "message": "Wstecz"
    },
    "close": 
    {
        "message": "Zamknij"
    },
    "show_extension_icon": 
    {
        "message": "W popup'ie użyj ikony pierwszego dodatku zamiast ikony kontekstu."
    },
    "open_notification": 
    {
        "message": "Kliknij tutaj aby zadecydować do jakich kontekstów checsz je dodać."
    }
}

================================================
FILE: _locales/pt_BR/messages.json
================================================
{
    "locale": 
    {
        "message": "en",
        "description": "There is build in @@_ui_locale variable but it shows language variations like en_GB, en_US etc. We don't want that."
    },
    "application_description": 
    {
        "message": "Separe as extensões em grupos e facilmente alterne entre eles."
    },
    "all_extensions": 
    {
        "message": "Todas as extensões"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "Destacar extensões sem grupo"
    },
    "create_new_context": 
    {
        "message": "Criar novo contexto"
    },
    "edit_context": 
    {
        "message": "Editar contexto"
    },
    "name_field_is_required": 
    {
        "message": "O campo Nome é obrigatório."
    },
    "this_name_is_already_in_use": 
    {
        "message": "Esse nome já está em uso."
    },
    "pick_an_icon": 
    {
        "message": "Escolha um ícone."
    },
    "available_extensions": 
    {
        "message": "Extensões disponíveis"
    },
    "always_enabled_extensions": 
    {
        "message": "Extensões sempre ativas"
    },
    "name": 
    {
        "message": "Nome"
    },
    "options": 
    {
        "message": "Opções"
    },
    "icon": 
    {
        "message": "Ícone"
    },
    "context_will_be_deleted": 
    {
        "message": "O contexto será excluído. Você tem certeza?"
    },
    "additional_options": 
    {
        "message": "Opções adicionais"
    },
    "new_context": 
    {
        "message": "Novo Contexto"
    },
    "save": 
    {
        "message": "Salvar"
    },
    "about": 
    {
        "message": "Sobre"
    },
    "configuration_import_export": 
    {
        "message": "Importar/exportar as configurações"
    },
    "configuration_import": 
    {
        "message": "Importar configuração"
    },
    "configuration_export_description": 
    {
        "message": "Para exportar todas as suas configurações, copie o código de configuração na caixa abaixo."
    },
    "configuration_import_description": 
    {
        "message": "Cole o código de configuração na caixa abaixo e clique em 'Importar' para restaurar sua configuração."
    },
    "confirm_configuration_import": 
    {
        "message": "A importação irá sobrescrever a sua configuração atual, certifique-se de que fez um backup se você não quer perdê-la."
    },
    "import": 
    {
        "message": "Importar"
    },
    "override_current_settings": 
    {
        "message": "Sobrescrever a configuração atual?"
    },
    "import_failed": 
    {
        "message": "Falha na importação"
    },
    "configuration_string_is_invalid": 
    {
        "message": "Desculpe, o código de configuração informado é inválido. A importação falhou."
    },
    "successful_import": 
    {
        "message": "Importação concluída"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "A configuração foi importada com sucesso."
    },
    "some_extensions_were_ignored": 
    {
        "message": "Algumas extensões da configuração importada foram ignoradas porque não estão mais instaladas:"
    },
    "override_server_settings": 
    {
        "message": "Sobrescrever a configuração no servidor?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "Sua configuração atual mantida no Chrome Sync será substituída. Você deseja continuar?"
    },
    "manual": 
    {
        "message": "Manual"
    },
    "chrome_sync": 
    {
        "message": "Chrome Sync"
    },
    "save_on_server": 
    {
        "message": "Salvar no servidor"
    },
    "load_from_server": 
    {
        "message": "Carregar do servidor"
    },
    "saved": 
    {
        "message": "Salvo"
    },
    "enable_apps_support": 
    {
        "message": "Ativar suporte a aplicativos (por padrão, somente extensões são suportadas)"
    },
    "show_all_extensions_button": 
    {
        "message": "Mostrar o botão 'Todas as extensões' no popup"
    },
    "delay_after_enabling_extension": 
    {
        "message": "espera em milisegundos após ativar cada extensão"
    },
    "context_options": 
    {
        "message": "Contexto - Opções"
    },
    "remove_context": 
    {
        "message": "Remover contexto?"
    },
    "cancel": 
    {
        "message": "Cancelar"
    },
    "edit": 
    {
        "message": "Editar"
    },
    "create": 
    {
        "message": "Criar"
    },
    "delete": 
    {
        "message": "Excluir"
    },
    "clone": 
    {
        "message": "Clonar"
    },
    "move": 
    {
        "message": "Mover"
    },
    "extension_is_loading": 
    {
        "message": "Carregando extensão..."
    },
    "new_extension_installed_action": 
    {
        "message": "quando nova extensão for instalada"
    },
    "ask_what_to_do": 
    {
        "message": "Perguntar o que fazer"
    },
    "add_to_all_contexts": 
    {
        "message": "Incluir a extensão em todos os contextos"
    },
    "add_to_always_enabled": 
    {
        "message": "Incluir em 'sempre ativas'"
    },
    "do_nothing": 
    {
        "message": "Não fazer nada"
    },
    "extension_installed_1": 
    {
        "message": "Nova extensão"
    },
    "extension_installed_2": 
    {
        "message": "instalada"
    },
    "add_to_contexts": 
    {
        "message": "Incluí-la nos seguintes contextos"
    },
    "or_add_it_to": 
    {
        "message": "ou incluí-la em"
    },
    "font": 
    {
        "message": "Fonte"
    },
    "icons": 
    {
        "message": "Ícones"
    },
    "icon_flip_animation": 
    {
        "message": "Animação do ícone"
    },
    "programmer": 
    {
        "message": "Programador"
    },
    "source_code": 
    {
        "message": "Código fonte"
    },
    "translations": 
    {
        "message": "Traduções"
    },
    "welcome": 
    {
        "message": "Bem vindo"
    },
    "welcome_step_1": 
    {
        "message": "Bem vindo! Para começar a trabalhar com essa extensão, crie os contextos (grupos de extensões). Para cada contexto escolha um nome e um ícone."
    },
    "welcome_step_2": 
    {
        "message": "Para conectar extensões aos contextos, arraste-as da listagem alfabética no topo da página para a caixa representando o contexto escolhido."
    },
    "welcome_step_3": 
    {
        "message": "Mova todas as extensões que deverão estar ativas em todos os contextos da caixa 'Extensões disponíveis' para a caixa 'Extensões sempre ativas'."
    },
    "welcome_step_4": 
    {
        "message": "Salve suas configurações e você terminou! Você pode alterar facilmente entre os contextos usando o ícone na barra de tarefas. Selecionando no menu o nome ou o ícone do contexto alterna para o contexto. Clicando nos botões mais/menos é possível ativar/desativar os contextos, permitindo mesclar um contexto com outros."
    },
    "next": 
    {
        "message": "Próximo"
    },
    "previous": 
    {
        "message": "Anterior"
    },
    "close": 
    {
        "message": "Fechar"
    },
    "show_extension_icon": 
    {
        "message": "Mostrar no menu o ícone da primeira extensão ao invés do ícone do contexto."
    },
    "open_notification": 
    {
        "message": "Clique aqui para selecionar o contexto para adicioná-la."
    }
}


================================================
FILE: _locales/zh_CN/messages.json
================================================
{
    "locale": 
    {
        "message": "zh_CN",
        "description": "浏览器内建 @@_ui_locale 变量,显示语言的变体如 en_GB 、en_US 等,我们并不需要。"
    },
    "application_description": 
    {
        "message": "分组排序扩展并轻易切换。"
    },
    "all_extensions": 
    {
        "message": "所有扩展"
    },
    "highlight_ungrouped_extensions": 
    {
        "message": "高亮尚未分组的扩展"
    },
    "create_new_context": 
    {
        "message": "建立新的 Context"
    },
    "edit_context": 
    {
        "message": "编辑 Context"
    },
    "name_field_is_required": 
    {
        "message": "必须填写名称。"
    },
    "this_name_is_already_in_use": 
    {
        "message": "这个名称已被使用。"
    },
    "pick_an_icon": 
    {
        "message": "选择一个图标。"
    },
    "available_extensions": 
    {
        "message": "可用扩展"
    },
    "always_enabled_extensions": 
    {
        "message": "保持启用扩展"
    },
    "name": 
    {
        "message": "名称"
    },
    "options": 
    {
        "message": "选项"
    },
    "icon": 
    {
        "message": "图标"
    },
    "context_will_be_deleted": 
    {
        "message": "Context 将被删除,是否确定?"
    },
    "additional_options": 
    {
        "message": "附加选项"
    },
    "new_context": 
    {
        "message": "新建 Context"
    },
    "save": 
    {
        "message": "保存"
    },
    "about": 
    {
        "message": "关于"
    },
    "configuration_import_export": 
    {
        "message": "导入/导出配置"
    },
    "configuration_import": 
    {
        "message": "配置导入"
    },
    "configuration_export_description": 
    {
        "message": "要导出你的配置,从下面的文本框复制经过编码的配置字符串。"
    },
    "configuration_import_description": 
    {
        "message": "粘帖配置字符串到下面的文本框并点击 ‘导入’ 来还原你的配置。"
    },
    "confirm_configuration_import": 
    {
        "message": "导入操作会覆盖你当前配置,请确保执行备份以免丢失。"
    },
    "import": 
    {
        "message": "导入"
    },
    "override_current_settings": 
    {
        "message": "覆盖当前设置?"
    },
    "import_failed": 
    {
        "message": "导入失败"
    },
    "configuration_string_is_invalid": 
    {
        "message": "抱歉,所提供的配置字符串无效。导入失败!"
    },
    "successful_import": 
    {
        "message": "导入成功"
    },
    "configuration_was_imported_successfuly": 
    {
        "message": "配置成功导入。"
    },
    "some_extensions_were_ignored": 
    {
        "message": "您所导入配置中的一些扩展由于还没有安装而被忽略:"
    },
    "override_server_settings": 
    {
        "message": "Override configuration on server?"
    },
    "confirm_chrome_sync_configuration_export": 
    {
        "message": "This will override your current configuration kept in Chrome Sync. Do you want to proceed?"
    },
    "manual": 
    {
        "message": "Manual"
    },
    "chrome_sync": 
    {
        "message": "Chrome Sync"
    },
    "save_on_server": 
    {
        "message": "Save on server"
    },
    "load_from_server": 
    {
        "message": "Load from server"
    },
    "saved": 
    {
        "message": "Saved"
    },
    "enable_apps_support": 
    {
        "message": "启用应用支持(默认仅仅支持扩展)"
    },
    "show_all_extensions_button": 
    {
        "message": "弹出菜单显示‘所有扩展’"
    },
    "delay_after_enabling_extension": 
    {
        "message": "启用每个扩展后等待的毫秒数"
    },
    "context_options": 
    {
        "message": "Context - 选项"
    },
    "remove_context": 
    {
        "message": "删除 Context ?"
    },
    "cancel": 
    {
        "message": "取消"
    },
    "edit": 
    {
        "message": "编辑"
    },
    "create": 
    {
        "message": "建立"
    },
    "delete": 
    {
        "message": "删除"
    },
    "clone": 
    {
        "message": "克隆"
    },
    "move": 
    {
        "message": "移动"
    },
    "extension_is_loading": 
    {
        "message": "正在载入扩展。。。"
    },
    "new_extension_installed_action": 
    {
        "message": "安装新的扩展之后"
    },
    "ask_what_to_do": 
    {
        "message": "询问如何处理"
    },
    "add_to_all_contexts": 
    {
        "message": "添加到所有的 Context"
    },
    "add_to_always_enabled": 
    {
        "message": "添加到 '永远启用'"
    },
    "do_nothing": 
    {
        "message": "什么也不要做"
    },
    "extension_installed_1": 
    {
        "message": "新的扩展"
    },
    "extension_installed_2": 
    {
        "message": "已经安装"
    },
    "add_to_contexts": 
    {
        "message": "把它添加到以下 Context"
    },
    "or_add_it_to": 
    {
        "message": "或者添加到"
    },
    "font": 
    {
        "message": "字体"
    },
    "icons": 
    {
        "message": "图标"
    },
    "icon_flip_animation": 
    {
        "message": "图标翻转动画"
    },
    "programmer": 
    {
        "message": "开发"
    },
    "source_code": 
    {
        "message": "源代码"
    },
    "translations": 
    {
        "message": "翻译"
    },
    "welcome": 
    {
        "message": "欢迎"
    },
    "welcome_step_1": 
    {
        "message": "欢迎!开始使用这个扩展之前,请先建立 Context (扩展组),并为每个 Context 选择一个名字和一个图标。"
    },
    "welcome_step_2": 
    {
        "message": "分组扩展,请从顶部按字母顺序排列的列表中拖拽扩展到相应的 Context 框中。"
    },
    "welcome_step_3": 
    {
        "message": "从 “可用扩展” 移动那些每个 Context 都应启用的扩展到 “保持启用扩展”。"
    },
    "welcome_step_4": 
    {
        "message": "保存配置即可!你可以使用工具栏上的图标轻易地在 Contexts 之间进行切换。通过选择菜单上的 Context 名称或者图标来切换到相应的 Context。点击 + 或者 - 号按钮激活或者关闭相应的 Context,这允许你混合使用各个不同的 Contexts。"
    },
    "next": 
    {
        "message": "前进"
    },
    "previous": 
    {
        "message": "后退"
    },
    "close": 
    {
        "message": "关闭"
    },
    "show_extension_icon": 
    {
        "message": "In the popup use icon of the first extension instead of the context icon."
    },
    "open_notification": 
    {
        "message": "Click here to decide what contexts you want to add it to."
    }
}

================================================
FILE: background.html
================================================
<html>
<head>
	<script src="js/libs/jquery-1.7.1.min.js"></script>

	<script src="js/classes/Configuration.class.js"></script>
	<script src="js/classes/ExtensionsManager.class.js"></script>
	<script src="js/classes/ContextsManager.class.js"></script>
	<script src="js/classes/IconAnimation.class.js"></script>
	<script src="js/classes/ExtensionNotification.class.js"></script>

	<script src='js/background.js' type='text/javascript'></script>
</head>
<body>
	<img id="image" src="icons/context.png" />
	<canvas id="canvas" width="19" height="19"></canvas>
</body>
</html>

================================================
FILE: css/main.css
================================================
/*
 * HTML5 Boilerplate
 *
 * What follows is the result of much research on cross-browser styling.
 * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
 * Kroc Camen, and the H5BP dev community and team.
 */


/* =============================================================================
   Base
   ========================================================================== */

/*html { font-size: 100%; overflow-y: scroll; -webkit-overflow-scrolling: touch; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }*/

body { margin: 0; font-size: 13px; line-height: 1.231; }

body, button, input, select, textarea { font-family: sans-serif; color: #222; }

::selection { background: #f6a828; color: #fff; text-shadow: none; }


/* =============================================================================
   Links
   ========================================================================== */

a { color: #00e; }
a:visited { color: #551a8b; }
a:focus { outline: thin dotted; }

/* Improve readability when focused and hovered in all browsers: people.opera.com/patrickl/experiments/keyboard/test */
a:hover, a:active { outline: 0; }


/* =============================================================================
   Typography
   ========================================================================== */

abbr[title] { border-bottom: 1px dotted; }

b, strong { font-weight: bold; }

blockquote { margin: 1em 40px; }

dfn { font-style: italic; }

hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }

ins { background: #ff9; color: #000; text-decoration: none; }

mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }

/* Redeclare monospace font family: en.wikipedia.org/wiki/User:Davidgothberg/Test59 */
pre, code, kbd, samp { font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 1em; }

/* Improve readability of pre-formatted text in all browsers */
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }

q { quotes: none; }
q:before, q:after { content: ""; content: none; }

small { font-size: 85%; }

/* Position subscript and superscript content without affecting line-height: gist.github.com/413930 */
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sup { top: -0.5em; }
sub { bottom: -0.25em; }


/* =============================================================================
   Lists
   ========================================================================== */

ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
dd { margin: 0 0 0 40px; }
nav ul, nav ol { list-style: none; margin: 0; padding: 0; }


/* =============================================================================
   Figures
   ========================================================================== */

figure { margin: 0; }


/* =============================================================================
   Forms
   ========================================================================== */

form { margin: 0; }
fieldset { border: 0; margin: 0; padding: 0; }

/* Indicate that 'label' will shift focus to the associated form element */
label { cursor: pointer; }

/*
 * 1. Correct font-size not inheriting in all browsers
 * 2. Remove margins in FF3/4 S5 Chrome
 * 3. Define consistent vertical alignment display in all browsers
 */

button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }

/*
 * 1. Display hand cursor for clickable form elements
 * 2. Allow styling of clickable form elements in iOS
 */

button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; }

/*
 * Consistent box sizing and appearance
 */

input[type="checkbox"], input[type="radio"] { box-sizing: border-box; }
input[type="search"] { -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }

/* 
 * Remove inner padding and border in FF3/4
 * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/ 
 */

button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }

/* Remove default vertical scrollbar in IE6/7/8/9 */
textarea { overflow: auto; vertical-align: top; }

/* Colors for form validity */
input:valid, textarea:valid {  }
input:invalid, textarea:invalid { background-color: #f0dddd; }


/* =============================================================================
   Tables
   ========================================================================== */

table { border-collapse: collapse; border-spacing: 0; }


/* =============================================================================
   Primary styles
   ========================================================================== */

/*Fonts*/
@font-face {
  font-family: 'Andika';
  font-style: normal;
  font-weight: normal;
  src: local('Andika'), url('../other/Andika.woff') format('woff');
}
/*Fonts*/

/*jQuery UI*/
.ui-selecting { background: #FECA40; }
.ui-selected { background: #F39814; color: white; }
.ui-selectable-helper { border: none; }
/*jQuery UI*/

h1 {
	margin-top: 0;
	font-size: 36px;
	font-family: 'Andika';
}

h2 {
	font-family: 'Andika';
	font-size: 18px;
	font-weight: normal;
	margin: 10px;
}

a {
	color: inherit;
}

a:visited {
	color: inherit;
}

.wrapper {
	margin: 15px;
	padding: 10px;
	box-shadow: #b3b3b3 0 0 25px;
	border-radius: 5px; 
	position: relative;
}

#content {
	display: none;
}

#loader {
	font-family: 'Andika';
}

#new-context-form {
}

	#new-context-form .dialog-label {
		font-weight: bold;
		display: block;
		margin-top: 15px;
		margin-bottom: 5px;
	}

	#new-context-form input.text {
		width: 100%;
		padding: 5px;
	}

	#new-context-form .errors {
		display: none;
	}

	#new-context-form .errors p {
		margin: 5px;
	}

#dialog-confirm, #dialog-import-success {
	display:none;
}

	#dialog-import-success ul {
		list-style: disc;
	}

#context-icons {
	list-style: none;
    padding: 0 5px 5px 0;
}

	#context-icons li {
		float: left;
		width: 40px;
		height: 40px;
		cursor: pointer;
		margin-left: 5px;
		margin-top: 5px;
	}

		#context-icons li img {
			margin-left: 4px;
			margin-top: 4px;
		}

#available_extensions_wrapper {
	position: relative;
	padding-left: 5px;
	padding-right: 5px;
}

#always_enabled_extensions_wrapper {
	margin-top: 10px;
	position: relative;
	padding-left: 5px;
	padding-right: 5px;
}

.top-right-box {
	position: absolute;
	right: 16px;
	top: 14px;
}

.extensions_list {
	list-style: none;
    padding: 5px 0;
    margin: 0 0 10px;
}

	.extensions_list li, ul.contextExtensions li {
		padding: 5px;
		line-height: 16px;
		width: auto;
		margin-top: 2px;
		cursor: move;
	}
	
	.extensions_list.active, ul.contextExtensions.active {
		background: url('ui-lightness/images/ui-bg_diagonals-thick.png') top left repeat;
		padding-bottom: 30px;
		padding-top: 30px;
	}
	
	.extensions_list.active_dense {
		background: url('ui-lightness/images/ui-bg_diagonals-thick.png') top left repeat;
	}
	
	.extensions_list.active_hover, ul.contextExtensions.active_hover {
		background: url('ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png') top left repeat;
	}

	ul.contextExtensions li:first-child {
		margin-top: 0;
	}

	.extensions_list li {
		float: left;
		margin-left: 2px;
	}

		.extensions_list img, ul.contextExtensions li img {
			vertical-align: -3px;
			width: 16px;
			height: 16px;
		}

		.extensions_list span.extensionName, ul.contextExtensions li span.extensionName {
			margin-left: 5px;
			font-size: 14px;
			text-overflow:ellipsis;
			overflow:hidden;
			white-space:nowrap;
			display: inline-block;
		}

		.extensions_list span.extensionName {
			width: 270px;
		}

		.extensions_list div.removeBtn {
			display: none;
		}

	.extensions_list li.ui-state-active {
		font-weight: normal;
	}

#contexts {
	list-style: none;
	margin: 0;
	padding: 0;
	width: 100%;
}

#contexts li.context {
	padding: 5px;
	float: left;
	display: block;
}

	#contexts li.context {
		margin-right: 10px;
		margin-top: 10px;
		position: relative;
	}

	#contexts li.context:last-child {
		margin-right: 0;
	}

	#contexts li.context span.contextTitle {
		font-family: 'Andika';
		font-size: 18px;
		line-height: 24px;
		margin-left: 5px;
		vertical-align: 8px;
		text-overflow:ellipsis;
		overflow:hidden;
		white-space:nowrap;
		display: inline-block;
		width: 240px;
	}

	.contextMenu {
		position: absolute;
		right: 5px;
		top: 2px;
	}

		.contextMenu a, .contextMenu div {
			margin: 0;
			padding: 0;
			display: inline-block;
		}

			.contextMenu a .ui-button-text {
				padding: 0;
			}

	.contextGrip {
		cursor: move;
	}

	ul.contextExtensions{
		list-style: none;
		margin: 10px 10px 10px 0;
		min-height: 16px;
		padding: 5px;
	}

		ul.contextExtensions li {
			position: relative;
		}

		ul.contextExtensions div.removeBtn {
			right: 5px;
			top: 3px;
			position: absolute;
			color: #1c94c4;
			border: none;
			margin: 0;
			padding: 0;
			background-color: transparent;
			cursor: pointer;
		}

		ul.contextExtensions li span.extensionName {
			width: 210px;
		}

#help-icon {
	position: absolute;
	right: 5px;
	top: 5px;
	cursor: pointer;
}

#accordion {
	margin-top: 30px;
}
	#accordion ul {
		list-style: none;
		padding: 0;
	}

	#accordion li {
		margin-top: 10px;
	}

	.hidden_feature {
		display: none;
	}

#welcome {
	display: none;
}

	#welcome ul {
		list-style: none;
		padding: 0;
	}

		#welcome div.picture {
			width: 480px;
			height: 320px;
			border: solid black 1px;
		}

		#welcome li.step_1 div.picture{
			background-image: url('../screenshots/__MSG_locale__/step_1.jpg');
		}

		#welcome li.step_2 div.picture{
			background-image: url('../screenshots/__MSG_locale__/step_2.jpg');
		}

		#welcome li.step_3 div.picture{
			background-image: url('../screenshots/__MSG_locale__/step_3.jpg');
		}
		
		#welcome li.step_4 div.picture{
			background-image: url('../screenshots/__MSG_locale__/step_4.jpg');
		}

#footer {
	border-top: solid silver 1px;
	padding-top: 20px;
	margin-top: 10px;
}

#popup {
	width: 222px;
}

	#popup * {
		box-sizing: border-box;
	}

	#popup .screenContainer {
		width: 200%;
		-webkit-transition: -webkit-transform 0.3s;
		transition: transform 0.3s;
		-webkit-transform: translateX(0);
		transform: translateX(0);
	}

		#popup .screenContainer.showExtensions {
			-webkit-transform: translateX(-50%);
			transform: translateX(-50%);
		}

		#popup .screenContainer > div {
			margin: 5px;
			float: left;
		}

		#popup #extensionsScreen .back-to-contexts {
			cursor: pointer;
		}

	ul.simple-list {
		position: relative;
		list-style: none;
		list-style-position: inside;
		padding: 0;
		margin: 0;
		overflow: hidden;
	}

		ul.simple-list li {
			margin: 0;
			margin-top: 2px;
			color: #363636;
			font-family: 'Andika';
		}

		ul.simple-list li:first-child{
			margin-top: 0;
		}
		
			ul.simple-list li div.list-context {
				padding: 2px 2px 2px 4px;
				cursor: pointer;
				float: left;
				width: 145px;
			}
			
				ul.simple-list li div.list-context span {
					margin-left: 5px;
				}

			ul.simple-list li div.list-item {
				padding: 2px 2px 2px 4px;
				cursor: pointer;
				width: 211px;
			}

				ul.simple-list li div.list-item span {
					display: inline-block;
				}

				ul.simple-list li div.list-item span.extension-name {
					width: 180px;
					white-space: nowrap;
					overflow: hidden;
					text-overflow: ellipsis;
					vertical-align: bottom;
				}

				ul.simple-list li div.list-item span.ui-icon {
					vertical-align: bottom;
				}

				ul.simple-list li div.list-item img {
					margin-right: 5px;
				}
			
			ul.simple-list li div.list-context.all-context {
				padding-left: 6px;
			}
			
			ul.simple-list li div.list-context.single-context {
				border-left: solid 3px #FFA6A6;
			}
			
			ul.simple-list li.status-partial div.list-context {
				border-left-color: #FFCE3B;
			}
			
			ul.simple-list li.status-all  div.list-context {
				border-left-color: #00C700;
			}
			
			ul.simple-list li div.list-button {
				cursor: pointer;
				float: left;
				padding: 2px;
			}

	ul.simple-list img{
		width: 16px;
		height: 16px;
		vertical-align: -3px;
	}

#notification {
	margin: 7px;
	min-height: 50px;
}

	#notification ul.simple-list {
		margin-bottom: 10px;
	}

		#notification ul.simple-list li div.list-context {
			float: none;
			width: auto;
		}

.inline-selectable {
	display: inline-block;
	padding: 2px;
	cursor: pointer;
}

#extensionName {
	color: #1c94c4;
	font-weight: bold;
}

#social-buttons {
	position: absolute;
	right: 0;
	bottom: 5px;
}

	#fb_share {
		display: inline-block;
		margin-right: 10px;
		vertical-align: top;
		height: 25px;
	}

#import-export-panel h2 {
	margin-top: 15px;
	margin-left: -10px;
}

#import-export-panel h2:nth-child(1) {
	margin-top: 0;
}

#import_box, #export_box {
	width: 100%;
	height: 40px;
	overflow-x: scroll;
	overflow-y: hidden;
	display: block;
}

/* =============================================================================
   Non-semantic helper classes
   Please define your styles before this section.
   ========================================================================== */

/* For image replacement */
.ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; text-align: left; direction: ltr; }
.ir br { display: none; }

/* Hide for both screenreaders and browsers:
   css-discuss.incutio.com/wiki/Screenreader_Visibility */
.hidden { display: none; visibility: hidden; }

/* Hide only visually, but have it available for screenreaders: by Jon Neal.
  www.webaim.org/techniques/css/invisiblecontent/  &  j.mp/visuallyhidden */
.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }

/* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: drupal.org/node/897638 */
.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }

/* Hide visually and from screenreaders, but maintain layout */
.invisible { visibility: hidden; }

/* Contain floats: nicolasgallagher.com/micro-clearfix-hack/ */ 
.clearfix:before, .clearfix:after { content: ""; display: table; }
.clearfix:after { clear: both; }
.clearfix { zoom: 1; }

/* Color by status */
.status-enabled { border-left: solid 3px #00C700 !important; }
.status-disabled { border-left: solid 3px #FFA6A6 !important; }
.float-left { float: left; }



/* =============================================================================
   PLACEHOLDER Media Queries for Responsive Design.
   These override the primary ('mobile first') styles
   Modify as content requires.
   ========================================================================== */

@media only screen and (min-width: 480px) {
  /* Style adjustments for viewports 480px and over go here */

}

@media only screen and (min-width: 768px) {
  /* Style adjustments for viewports 768px and over go here */

}


/* =============================================================================
   Print styles.
   Inlined to avoid required HTTP connection: www.phpied.com/delay-loading-your-print-css/
   ========================================================================== */
 
@media print {
  * { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: sanbeiji.com/archives/953 */
  a, a:visited { color: #444 !important; text-decoration: underline; }
  a[href]:after { content: " (" attr(href) ")"; }
  abbr[title]:after { content: " (" attr(title) ")"; }
  .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }  /* Don't show links for images, or javascript/internal links */
  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
  thead { display: table-header-group; } /* css-discuss.incutio.com/wiki/Printing_Tables */
  tr, img { page-break-inside: avoid; }
  img { max-width: 100% !important; }
  @page { margin: 0.5cm; }
  p, h2, h3 { orphans: 3; widows: 3; }
  h2, h3{ page-break-after: avoid; }
}


================================================
FILE: css/ui-lightness/jquery-ui-1.8.17.custom.css
================================================
/*
 * jQuery UI CSS Framework 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Theming/API
 */

/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
.ui-helper-clearfix:after { clear: both; }
.ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }


/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }


/* Icons
----------------------------------*/

/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }


/* Misc visuals
----------------------------------*/

/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }


/*
 * jQuery UI CSS Framework 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Theming/API
 *
 * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
 */


/* Component containers
----------------------------------*/
.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
.ui-widget-content a { color: #333333; }
.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
.ui-widget-header a { color: #ffffff; }

/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; }
.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; }
.ui-widget :active { outline: none; }

/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }

/* Icons
----------------------------------*/

/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }

/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }


/* Misc visuals
----------------------------------*/

/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }

/* Overlays */
.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/*
 * jQuery UI Resizable 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Resizable#theming
 */
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
 * jQuery UI Selectable 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectable#theming
 */
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
/*
 * jQuery UI Accordion 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Accordion#theming
 */
/* IE/Win - Fix animation bug - #4615 */
.ui-accordion { width: 100%; }
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }
/*
 * jQuery UI Autocomplete 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Autocomplete#theming
 */
.ui-autocomplete { position: absolute; cursor: default; }	

/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */

/*
 * jQuery UI Menu 1.8.17
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Menu#theming
 */
.ui-menu {
	list-style:none;
	padding: 2px;
	margin: 0;
	display:block;
	float: left;
}
.ui-menu .ui-menu {
	margin-top: -3px;
}
.ui-menu .ui-menu-item {
	margin:0;
	padding: 0;
	zoom: 1;
	float: left;
	clear: left;
	width: 100%;
}
.ui-menu .ui-menu-item a {
	text-decoration:none;
	display:block;
	padding:.2em .4em;
	line-height:1.5;
	zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
	font-weight: normal;
	margin: -1px;
}
/*
 * jQuery UI Button 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Button#theming
 */
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; } 
button.ui-button-icons-only { width: 3.7em; } 

/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4;  }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }

/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }

/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }

/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
/*
 * jQuery UI Dialog 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Dialog#theming
 */
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/*
 * jQuery UI Slider 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Slider#theming
 */
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }

.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }

.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
 * jQuery UI Tabs 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Tabs#theming
 */
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }
/*
 * jQuery UI Datepicker 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Datepicker#theming
 */
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month, 
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }

/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }

/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }

/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
    display: none; /*sorry for IE5*/
    display/**/: block; /*sorry for IE5*/
    position: absolute; /*must have*/
    z-index: -1; /*must have*/
    filter: mask(); /*must have*/
    top: -4px; /*must have*/
    left: -4px; /*must have*/
    width: 200px; /*must have*/
    height: 200px; /*must have*/
}/*
 * jQuery UI Progressbar 1.8.17
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Progressbar#theming
 */
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }

================================================
FILE: gfx/promo/large-promo-less-icons.xcf
================================================
[File too large to display: 19.5 MB]

================================================
FILE: js/background.js
================================================
var contextsManager = new ContextsManager();
var extensionsManager = new ExtensionsManager();
var iconAnimation;

function init() {
	iconAnimation = new IconAnimation({
		canvasObj: document.getElementById('canvas'),
		imageObj: document.getElementById('image'),
		defaultIcon: "icons/context.png"
	});

	if(CONFIG.get('firstRun') == 'yes') {
		openConfig();
	}
}

/*CONTEXT CHANGING*/
function reloadConfiguration(callback) {
	//show animation
	iconAnimation.animate("icons/context_cog.png");

	//reload list of all extensions and always enabled extensions
	extensionsManager.init(callback);
}

function enableAllExtensions() {
	reloadConfiguration(function() {
		extensionsManager.enableAllExtensions();
	});
}

function disableAllExtensions() {
	reloadConfiguration(function() {
		extensionsManager.disableAllExtensions();
	});
}

function changeContext(selectedContext) {
	reloadConfiguration(function() {
		//change context
		var context = contextsManager.getContext(selectedContext);

		if(context) {
			var allExtensions = extensionsManager.getExtensionsList();
			var enableList = [];
			var disableList = [];

			//check which extensions should be enabled and which should be disabled
			for(var i in allExtensions) {
				var extension = allExtensions[i];
				var found = false;

				//first, check if extension should be always enabled, if not, check if it is enabled in given context
				if(extensionsManager.isAlwaysEnabled(extension.id)) {
					found = true;
				} else {
					found = contextsManager.isInContext(context, extension);
				}

				if(found) {
					enableList.push(extension);
				} else {
					disableList.push(extension);
				}
			}

			//disable extensions first, then enable extensions
			extensionsManager.disableExtensions(disableList, function(){
				extensionsManager.enableExtensions(enableList);
			});
		}
	});
}

function activateContext(selectedContext) {
	reloadConfiguration(function() {
		//activate context
		var context = contextsManager.getContext(selectedContext);

		if(context){
			var allExtensions = extensionsManager.getExtensionsList();
			var enableList = [];

			//check which extensions should be enabled
			for(var i in allExtensions) {
				var extension = allExtensions[i];
				var found = false;

				//first, check if extension should be always enabled, if not, check if it is enabled in given context
				if(extensionsManager.isAlwaysEnabled(extension.id)) {
					found = true;
				} else {
					found = contextsManager.isInContext(context, extension);
				}

				if(found) {
					enableList.push(extension);
				}
			}

			//enable extensions
			extensionsManager.enableExtensions(enableList);
		}
	});
}

function deactivateContext(selectedContext) {
	reloadConfiguration(function() {
		//activate context
		var context = contextsManager.getContext(selectedContext);

		if(context){
			var allExtensions = extensionsManager.getExtensionsList();
			var disableList = [];

			//check which extensions should be disabled
			for(var i in allExtensions) {
				var extension = allExtensions[i];
				var found = false;

				//skip always enabled extensions
				if(extensionsManager.isAlwaysEnabled(extension.id)) {
					continue;
				} else {
					found = contextsManager.isInContext(context, extension);
				}

				if(found) {
					disableList.push(extension);
				}
			}

			//disable extensions
			extensionsManager.disableExtensions(disableList);
		}
	});
}

function configUpdated() {
	contextsManager.init();
	extensionsManager.init();

	iconAnimation.animate("icons/context_wrench.png");
}

/* NEW EXTENSION INSTALLATION */
var newestExtension;

function getNewestExtension() {
	return newestExtension;
}

chrome.management.onInstalled.addListener(function(extdata) {
	//ignore themes
	if(extdata.type === 'theme') {
		return;
	}

	//if app support is disabled do nothing
	if(extdata.isApp && CONFIG.get('appsSupport') !== 'true') {
		return;
	}

	//check if extension exist in list of known extensions - hack to distinguish between extension installation and update
	if( extensionsManager.getExtensionData( extdata.id ) ) {
		return;//just an update
	}

	var contexts = contextsManager.getContextsList();

	if(contexts.length > 0 && CONFIG.get('newExtensionAction') === 'add_to_all') {
		for(var i in contexts) {
			contextsManager.addExtensionToContext( contexts[i], extdata.id );
		}

		contextsManager.save();
		configUpdated();
	} else if(CONFIG.get('newExtensionAction') === 'add_to_always_enabled') {
		extensionsManager.addExtensionToAlwaysEnabled( extdata.id );
		extensionsManager.save();
		configUpdated();
	} else if (CONFIG.get('newExtensionAction') === 'ask') {
		//fetching last (biggest) icon if it exists, otherwise using Context icon
		var icon = (extdata.icons && extdata.icons.length) ? (extdata.icons[extdata.icons.length - 1].url) : ('icons/context-128.png');

		var notification = new ExtensionNotification({
			icon: icon,
			title: chrome.i18n.getMessage("extension_installed_1") + ' ' + extdata.name + ' ' + chrome.i18n.getMessage("extension_installed_2"),
			body: chrome.i18n.getMessage("open_notification"),
			onclick: function () {
				var w = 300,
					h = 400,
					t = screen.height - h - 10,
					l = screen.width - w - 10;

				chrome.windows.create({
					'url': 'notification.html',
					'type': 'popup',
					'focused': true,
					'width': w,
					'height': h,
					'top': t,
					'left': l
				});
			}
		});

		newestExtension = extdata;
		notification.show();
	}
});

chrome.management.onUninstalled.addListener(function(extid) {
	//remove extension from all contexts
	var contexts = contextsManager.getContextsList();
	for(var i in contexts) {
		contextsManager.removeExtensionFromContext( contexts[i], extid );
	}
	contextsManager.save();

	//remove extension from always enabled extensions
	extensionsManager.removeExtensionFromAlwaysEnabled( extid );
	extensionsManager.save();

	//update list of known extensions
	extensionsManager.init();
});

//open extension config page
function openConfig() {
	chrome.tabs.getAllInWindow(null, function(tabs) {

		for(var i= 0, l=tabs.length; i<l;i++) {
			var tab = tabs[i];
			if(tab.url.indexOf(chrome.extension.getURL("options.html")) === 0) {
				chrome.tabs.update(tab.id, {
					url: chrome.extension.getURL("options.html"),
					selected: true
				});
				return;
			}
		}

		chrome.tabs.create({
			url:chrome.extension.getURL("options.html"),
			selected: true
		});
	});
}

$(document).ready(function() {
	init();
});


================================================
FILE: js/classes/Configuration.class.js
================================================
function Configuration() {
	"use strict";
	var constants = {
		iconsPath: 'icons/dortmund/',
		icons: ['home', 'search', 'world', 'heart', 'lightbulb', 'basket', 'customers', 'hire-me', 'administrative-docs', 'comment', 'config', 'finished-work', 'settings', 'star'],
		extensionName: 'Context',
		configBackupFormatVersion: 1
	};

	var defaults = {
		appsSupport: 'false',
		extensionEnableDelay: 200,//ms
		showLoadAllBtn: 'true',
		newExtensionAction: 'ask',
		firstRun: 'yes',
		highlightUngroupedExtensions: 'false'
	};

	/**
	 * Returns value of a config parameter (constant, user setting or default setting) with provided name.
	 * Returns null if no matching parameter is found.
	 * @param {string} name
	 * @returns {string|Array|number|null}
	 */
	this.get = function (name) {
		return constants[name] || localStorage[name] || defaults[name] || null;
	};
}

var CONFIG = new Configuration();

================================================
FILE: js/classes/ConfigurationBackupExporter.class.js
================================================
function ConfigurationBackupExporter() {
	"use strict";
	var extensionsManager;

	/**
	 * Creates dump (base64 encoded JSON) of whole configuration. Value is returned via callback.
	 * @param {function(string)} callback
	 */
	this.exportConfig = function (callback) {
		var contextsManager = new ContextsManager();
		extensionsManager = new ExtensionsManager(function () {
			var contexts = contextsManager.getContextsList();
			var alwaysEnabledExtensions = extensionsManager.getAlwaysEnabledExtensionsIds();
			var extensionsNamesDictionary = createExtensionsNamesDictionary(contexts, alwaysEnabledExtensions);

			var cleanConfig = {
				"version": CONFIG.get("configBackupFormatVersion"),
				"contexts": contexts,
				"alwaysEnabledExtensions": alwaysEnabledExtensions,
				"extensionsNamesDictionary": extensionsNamesDictionary,
				"advancedOptions": {
					"appsSupport": CONFIG.get("appsSupport"),
					"newExtensionAction": CONFIG.get("newExtensionAction"),
					"showLoadAllBtn": CONFIG.get("showLoadAllBtn")
				}
			};

			var encodedConfig = Base64.encode(JSON.stringify(cleanConfig));

			if (typeof callback === 'function') {
				callback(encodedConfig);
			}
		});
	};

	var createExtensionsNamesDictionary = function (contexts, alwaysEnabledExtensions) {
		var extid, cindex, eindex;
		var extensionsNamesDictionary = {};

		for (cindex in contexts) {
			var context = contexts[cindex];

			for (eindex in context.extensions) {
				extid = context.extensions[eindex].id;

				extensionsNamesDictionary[extid] = '';
			}
		}

		for (var i = 0; i < alwaysEnabledExtensions.length; i++) {
			extid = alwaysEnabledExtensions[i];

			extensionsNamesDictionary[extid] = '';
		}

		for (extid in extensionsNamesDictionary) {
			var extension = extensionsManager.getExtensionData(extid);

			if (extension) {
				extensionsNamesDictionary[extid] = extension.name;
			}
		}

		return extensionsNamesDictionary;
	};
}

================================================
FILE: js/classes/ConfigurationBackupImporter.class.js
================================================
function ConfigurationBackupImporter() {
	"use strict";
	/**
	 * Array of errors that occurred during last import.
	 * @type {Array.<string>}
	 */
	var errors = [];
	/**
	 * List of extensions mentioned in imported configuration but not installed.
	 * @type {Array.<Object>}
	 */
	var missingExtensions = [];
	/**
	 * @type {ExtensionsManager}
	 */
	var extensionsManager;

	/**
	 * Tries to import given encoded configuration. If no critical errors are found boolean 'true' is returned via callback as a first parameter and
	 * imported configuration replaces current Context configuration.
	 * Second parameter returned to the callback will contain list of extensions mentioned in imported config but currently not installed.
	 * Third parameter returned to the callback will contain list of errors encountered during import.
	 * @param {string} encodedConfig base64 encoded JSON
	 * @param {function(boolean, Array.<Object>, Array.<string>): void=} callback
	 */
	this.importConfig = function (encodedConfig, callback) {
		extensionsManager = new ExtensionsManager(function () {
			var jsonString = Base64.decode(jQuery.trim(encodedConfig));
			var json;

			errors = [];
			missingExtensions = [];

			try {
				json = JSON.parse(jsonString);
			} catch (e) {
				errors.push('JSON parser error: ' + e.type);
			}

			if (typeof json === "object") {
				validateStructure(json);

				//we proceed only if there were no errors in the root structure
				if (errors.length === 0) {
					validateVersion(json.version);
					validateContexts(json.contexts, json.extensionsNamesDictionary);
					validateAlwaysEnabledExtensions(json.alwaysEnabledExtensions, json.extensionsNamesDictionary);
					validateAdvancedOptions(json.advancedOptions);
				}
			} else {
				errors.push('Corrupted configuration string.');
			}

			if (errors.length === 0) {
				updateConfiguration(json);
			}

			if (typeof callback === 'function') {
				var status = (errors.length === 0);
				callback(status, missingExtensions, errors);
			}
		});
	};

	this.getMissingExtensions = function () {
		return missingExtensions;
	};

	this.getErrors = function () {
		return errors;
	};

	var validateStructure = function (config) {
		if (!config.hasOwnProperty("version") || !config.hasOwnProperty("contexts") || !config.hasOwnProperty("alwaysEnabledExtensions") || !config.hasOwnProperty("extensionsNamesDictionary") || !config.hasOwnProperty("advancedOptions")) {
			errors.push('Configuration object is missing one or more root property.');
		}
	};

	var validateVersion = function (version) {
		if (version !== 1) {
			errors.push('Unknown configuration file format version.');
		}
	};

	var validateContexts = function (contexts, dictionary) {
		if (!jQuery.isArray(contexts)) {
			errors.push('List of contexts is not an object.');
		} else {
			for (var index in contexts) {
				var context = contexts[index];

				validateContext(context, dictionary);
			}
		}
	};

	var validateContext = function (context, dictionary) {
		if (!context.hasOwnProperty("extensions") || !context.hasOwnProperty("imgSrc") || !context.hasOwnProperty("name")) {
			errors.push('Context object is missing one or more properties.');
		} else {
			if (!jQuery.isArray(context.extensions)) {
				errors.push('List of extensions in context is not an array.');
			} else {
				//store only valid extensions
				context.extensions = context.extensions.filter(function (extension, idx, array) {
					return validateExtension(extension.id, dictionary);
				});
			}
		}
	};

	var validateExtension = function (extid, dictionary) {
		//check if extension is currently installed
		var index;
		var extension = extensionsManager.getExtensionData(extid);

		if (!extension) {
			//check if extension is not already on a list of missing extensions
			for (index in missingExtensions) {
				if (missingExtensions[index].id === extid) {
					return false;
				}
			}

			missingExtensions.push({
				id: extid,
				name: dictionary.hasOwnProperty(extid) ? dictionary[extid] : '-unknown-'
			});

			return false;
		}

		return true;
	};

	var validateAlwaysEnabledExtensions = function (extensions, dictionary) {
		if (!jQuery.isArray(extensions)) {
			errors.push('Always enabled extensions is not an array.');
		} else {
			var validExtensions = extensions.filter(function (extension, idx, array) {
				return validateExtension(extension, dictionary);
			});

			extensions.length = 0;
			for (var i = 0; i < validExtensions.length; i++) {
				extensions.push(validExtensions[i]);
			}
		}
	};

	var validateAdvancedOptions = function (config) {
		if (config.hasOwnProperty("appsSupport") && (jQuery.inArray(config.appsSupport, ["true", "false"]) === -1)) {
			errors.push('Invalid "appsSupport" value.');
		}
		if (config.hasOwnProperty("newExtensionAction") && (jQuery.inArray(config.newExtensionAction, ["ask", "add_to_all", "add_to_always_enabled", "do_nothing"]) === -1)) {
			errors.push('Invalid "newExtensionAction" value.' + config.newExtensionAction);
		}
		if (config.hasOwnProperty("showLoadAllBtn") && (jQuery.inArray(config.showLoadAllBtn, ["true", "false"]) === -1)) {
			errors.push('Invalid "showLoadAllBtn" value.' + config.showLoadAllBtn);
		}
	};

	var updateConfiguration = function (config) {
		if (config.advancedOptions.hasOwnProperty("appsSupport")) {
			localStorage.appsSupport = config.advancedOptions.appsSupport;
		}
		if (config.advancedOptions.hasOwnProperty("newExtensionAction")) {
			localStorage.newExtensionAction = config.advancedOptions.newExtensionAction;
		}
		if (config.advancedOptions.hasOwnProperty("showLoadAllBtn")) {
			localStorage.showLoadAllBtn = config.advancedOptions.showLoadAllBtn;
		}

		//import contexts
		localStorage.contexts = JSON.stringify(config.contexts);

		//import alwaysEnabledExtensions
		localStorage.alwaysEnabledExtensions = JSON.stringify(config.alwaysEnabledExtensions);

		//reload bg page settings
		chrome.extension.getBackgroundPage().configUpdated();
	};
}

================================================
FILE: js/classes/ContextsManager.class.js
================================================
function ContextsManager() {
	"use strict";
	var that = this;
	/**
	 * List of all contexts.
	 * @type {Array.<Object>}
	 */
	var contextsList = [];

	this.init = function () {
		if (localStorage.contexts) {
			that.setContextsList(JSON.parse(localStorage.contexts));
		}
	};

	/**
	 * Returns list of contexts with current statuses (enabled/disabled/partial).
	 * This operation is asynchronous - result list is returned to a callback.
	 * @param {function(Array.<Object>): void} callback
	 */
	this.getContextsListWithStatuses = function (callback) {
		chrome.management.getAll(function (extensions) {
			var contextsListsWithStatuses, activeExtensions = [];

			//make handy array of active extension ids
			activeExtensions = extensions.filter(function (extension) {
				return extension.enabled;
			}).map(function (extension) {
					return extension.id;
				});

			contextsListsWithStatuses = [];

			//check all contexts
			contextsList.forEach(function (context) {
				var countActive, status;

				countActive = context.extensions.filter(function (extension) {
					return ( activeExtensions.indexOf(extension.id) !== -1 );
				}).length;

				if (countActive === context.extensions.length) {//context is enabled (all extensions are active)
					status = "enabled";
				} else if (countActive === 0) {//context is disabled (no active extensions)
					status = "disabled";
				} else {//context is partially enabled (some active extensions)
					status = "partial";
				}

				//clone context object and add status
				contextsListsWithStatuses.push({
					name: context.name,
					imgSrc: context.imgSrc,
					icon: context.icon,
					extensions: context.extensions,
					status: status
				});
			});

			if (typeof callback === "function") {
				callback(contextsListsWithStatuses);
			}
		});
	};

	this.setContextsList = function (list) {
		contextsList = list;
	};

	/**
	 * Returns list of context objects.
	 * @returns {Array.<Object>}
	 */
	this.getContextsList = function () {
		return contextsList;
	};

	/**
	 * Checks if given extension is part of given context.
	 * @param {Object|string} context
	 * @param {Object|string} extension
	 * @returns {boolean}
	 */
	this.isInContext = function (context, extension) {
		var extid, contextObj, j;

		extid = (typeof extension === "object") ? extension.id : extension;
		contextObj = (typeof context === "string") ? that.getContext(context) : context;

		for (j in contextObj.extensions) {
			if (contextObj.extensions[j].id === extid) {
				return true;
			}
		}

		return false;
	};

	/**
	 * Returns context by name or false if not found.
	 * @param {string} name
	 * @returns {Object|boolean}
	 */
	this.getContext = function (name) {
		var cindex, context;

		for (cindex in contextsList) {
			context = contextsList[cindex];

			if (context.name === name) {
				return context;
			}
		}

		return false;
	};

	/**
	 * Checks if given context exists.
	 * @param {string} name
	 * @returns {boolean}
	 */
	this.contextExists = function (name) {
		return (this.getContext(name) !== false);
	};

	/**
	 * Adds single extension to the given context.
	 * @param {Object|string} context
	 * @param {Object|string} extension
	 */
	this.addExtensionToContext = function (context, extension) {
		var extid, contextName, contextObj;

		extid = (typeof extension === "object") ? extension.id : extension;
		contextName = (typeof context === "object") ? context.name : context;

		contextObj = that.getContext(contextName);

		if (contextObj && !that.isInContext(contextObj, extid)) {
			contextObj.extensions.push({
				id: extid
			});
		}
	};

	/**
	 * Removes single extension form given context.
	 * @param {Object|string} context
	 * @param {Object|string} extension
	 */
	this.removeExtensionFromContext = function (context, extension) {
		var extid, contextName, contextObj;

		extid = (typeof extension === "object") ? extension.id : extension;
		contextName = (typeof context === "object") ? context.name : context;

		contextObj = that.getContext(contextName);

		if (contextObj) {
			contextObj.extensions = contextObj.extensions.filter(function (item) {
				return (item.id !== extid);
			});
		}
	};

	/**
	 * Creates new, empty context.
	 * @param {string} name
	 * @param {string} img icon URL
	 */
	this.newContext = function (name, img) {
		var contextObj = {
			'name': name,
			'imgSrc': img,
			'extensions': []
		};
		contextsList.push(contextObj);
		that.save();
	};

	/**
	 * Saves current contexts to localStorage.
	 */
	this.save = function () {
		localStorage.contexts = JSON.stringify(contextsList);
	};

	this.init(); //constructor
}

================================================
FILE: js/classes/ExtensionNotification.class.js
================================================
function ExtensionNotification(options) {
	"use strict";
	var useChromeNotifications = (chrome && chrome.notifications);
	var defaults = { icon: 'icons/context-128.png', title: '', body: '' };
	var settings = $.extend({}, defaults, options);
	var notification = null;

	this.show = function () {
		//ATM only osx, windows and chrome os support chrome.notifications
		if (useChromeNotifications) {
			notification = chrome.notifications.create(settings.title, {
				type: "basic",
				title: settings.title,
				message: settings.body,
				iconUrl: settings.icon
			}, function (notificationID) {
				notification = notificationID;
			});

			if(settings.onclick) {
				chrome.notifications.onClicked.addListener(function(notificationID) {
					if(notification === notificationID) {
						settings.onclick();
					}
				});
			}
		} else if (window.Notification) {
			//we use default HTML5 notifications for Linux
			notification = new Notification(settings.title, {body: settings.body, icon: settings.icon});

			if(settings.onclick) {
				notification.onclick = settings.onclick;
			}
		}
	};
}

================================================
FILE: js/classes/ExtensionsManager.class.js
================================================
function ExtensionsManager(onLoadCallback) {
	"use strict";
	var that = this;
	/**
	 * List of all installed extensions.
	 * @type {Array.<Object>}
	 */
	var extensionsList = [];
	/**
	 * List of IDs of 'always enabled' extensions.
	 * @type {Array.<string>}
	 */
	var alwaysEnabledExtensionsIds = [];

	this.init = function (callback) {
		chrome.management.getAll(function (list) {
			that.setExtensionsList(list);

			if (typeof callback === 'function') {
				callback();
			}
		});

		if (localStorage.alwaysEnabledExtensions) {
			that.setAlwaysEnabledExtensionsIds(JSON.parse(localStorage.alwaysEnabledExtensions));
		}
	};

	this.setExtensionsList = function (list) {
		var contextExtensionId = chrome.i18n.getMessage("@@extension_id");

		extensionsList = list.sort(function (item1, item2) { //sort by name
			if (item1.name < item2.name) {
				return -1;
			}

			return 1;
		}).filter(function (element) {
			//remove Context itself from manageable extensions
			//remove themes as support for multiple themes is very unstable
			return ( element.id !== contextExtensionId && element.type !== 'theme' );
		});
	};

	/**
	 * Returns list of all extensions.
	 * @returns {Array.<Object>}
	 */
	this.getExtensionsList = function () {
		return extensionsList;
	};

	this.setAlwaysEnabledExtensionsIds = function (list) {
		alwaysEnabledExtensionsIds = list;
	};

	/**
	 * Returns list of 'always enabled' extensions.
	 * @returns {Array.<Object>}
	 */
	this.getAlwaysEnabledExtensionsIds = function () {
		return alwaysEnabledExtensionsIds;
	};

	/**
	 * Removes single extension from 'always enabled extensions'
	 * @param {string} extid
	 */
	this.removeExtensionFromAlwaysEnabled = function (extid) {
		alwaysEnabledExtensionsIds = alwaysEnabledExtensionsIds.filter(function (item) {
			return (item !== extid);
		});
	};

	/**
	 * Adds single exetnsion to 'always enabled extensions'
	 * @param {string} extid
	 */
	this.addExtensionToAlwaysEnabled = function (extid) {
		if (!that.isAlwaysEnabled(extid)) {
			alwaysEnabledExtensionsIds.push(extid);
		}
	};

	/**
	 * Saves 'always enabled extensions' to localStorage
	 */
	this.save = function () {
		localStorage.alwaysEnabledExtensions = JSON.stringify(alwaysEnabledExtensionsIds);
	};

	/**
	 * Returns extension details based on extension ID.
	 * @param {string} extid
	 * @returns {Object|boolean}
	 */
	this.getExtensionData = function (extid) {
		var index;

		for (index in extensionsList) {
			var extension = extensionsList[index];

			if (extension.id === extid) {
				return extension;
			}
		}

		return false;
	};

	/**
	 * Returns true if extension is in 'always enabled' group.
	 * @param {string} extid
	 * @returns {boolean}
	 */
	this.isAlwaysEnabled = function (extid) {
		return (jQuery.inArray(extid, alwaysEnabledExtensionsIds) !== -1);
	};

	/**
	 * Enables all extensions.
	 */
	this.enableAllExtensions = function () {
		that.enableExtensions(that.getExtensionsList());
	};

	/**
	 * Enables list of extensions one by one. Calls optional callback when all extensions from the list are enabled.
	 * @param {Array.<Object>} list
	 * @param {function(): void=} callback
	 */
	this.enableExtensions = function (list, callback) {
		if (list.length > 0) {
			var extension = list.pop();

			that.enableExtension(extension, true, function () {
				window.setTimeout(function () {
					that.enableExtensions(list, callback);
				}, CONFIG.get('extensionEnableDelay'));
			});
		}

		if (typeof callback === "function") {
			callback();
		}
	};

	/**
	 * Enables or disables single extension. Calls optional callback when operation is finished.
	 * @param {Object} extension
	 * @param {boolean} enable
	 * @param {function(): void=} callback
	 */
	this.enableExtension = function (extension, enable, callback) {
		if (
			extension.type !== 'theme' && //do not touch themes
			(!extension.isApp || CONFIG.get('appsSupport') === 'true') && //check if extension is an app and continue only if we support apps
			((enable === true && !extension.enabled) || (enable === false && extension.enabled && extension.mayDisable)) && //enable extension if it is not already enabled, disable extension if it can be disabled and is not already disabled
			(extension.id !== chrome.i18n.getMessage("@@extension_id")) //do not enable/disable current extension (Context)
		) {
			if (typeof callback === "function") {
				chrome.management.setEnabled(extension.id, enable, callback);
			} else {
				chrome.management.setEnabled(extension.id, enable);
			}
		} else if (typeof callback === "function") {
			callback();
		}
	};

	/**
	 * Disables all extensions.
	 */
	this.disableAllExtensions = function () {
		that.disableExtensions(that.getExtensionsList());
	};

	/**
	 * Disables list of extensions one by one. Calls optional callback when all extensions from the list are disabled.
	 * @param {Array.<Object>} list
	 * @param {function(): void=} callback
	 */
	this.disableExtensions = function (list, callback) {
		var i;

		if (list.length > 0) {
			for (i in list) {
				var extension = list[i];
				that.disableExtension(extension);
			}
		}

		if (typeof callback === "function") {
			callback();
		}
	};

	/**
	 * Disable single extension (alias method).
	 * @param {Object} extension
	 */
	this.disableExtension = function (extension) {
		that.enableExtension(extension, false);
	};

	this.init(onLoadCallback);//constructor
}


================================================
FILE: js/classes/HugeStorageSync.class.js
================================================
function HugeStorageSync() {
	"use strict";

	function getCacheKey(key, i) {
		return (i === 0) ? key : key + "_" + i;
	}

	/**
	 * Allows to save strings longer than QUOTA_BYTES_PER_ITEM in chrome.storage.sync by splitting them into smaller parts.
	 * Please note that you still can't save more than QUOTA_BYTES.
	 *
	 * @param {string} key
	 * @param {string} value
	 * @param {function(): void=} callback
	 */
	this.set = function(key, value, callback) {
		var i = 0,
			cache = {},
			segment,
			cacheKey;

		// split value into chunks and store them in an object indexed by `key_i`
		while(value.length > 0) {
			cacheKey = getCacheKey(key, i);
			//if you are wondering about -2 at the end see: https://code.google.com/p/chromium/issues/detail?id=261572
			segment = value.substr(0, chrome.storage.sync.QUOTA_BYTES_PER_ITEM - cacheKey.length - 2);
			cache[cacheKey] = segment;
			value = value.substr(chrome.storage.sync.QUOTA_BYTES_PER_ITEM - cacheKey.length - 2);
			i++;
		}

		// store all the chunks
		chrome.storage.sync.set(cache, callback);

		//we need to make sure that after the last chunk we have an empty chunk. Why this is so important?
		// Saving v1 of our object. Chrome sync status: [chunk1v1] [chunk2v1] [chunk3v1]
		// Saving v2 of our object (a bit smaller). Chrome sync status: [chunk1v2] [chunk2v2] [chunk3v1]
		// When reading this configuration back we will end up with chunk3v1 being appended to the chunk1v2+chunk2v2
		chrome.storage.sync.remove(getCacheKey(key, i));
	};


	/**
	 * Retrieves chunks of value stored in chrome.storage.sync and combines them.
	 *
	 * @param {string} key
	 * @param {function(string):void=} callback
	 */
	this.get = function(key, callback) {
		//get everything from storage
		chrome.storage.sync.get(null, function(items) {
			var i, value = "";

			for(i=0; i<chrome.storage.sync.MAX_ITEMS; i++) {
				if(items[getCacheKey(key, i)] === undefined) {
					break;
				}
				value += items[getCacheKey(key, i)];
			}

			callback(value);
		});
	};
}

================================================
FILE: js/classes/IconAnimation.class.js
================================================
function IconAnimation(config) {
	"use strict";
	var animationFrames = 36,
		animationSpeed = 10,//ms
		rotation = 0,
		canvas = config.canvasObj,
		canvasContext,
		image = config.imageObj,
		defaultIcon = config.defaultIcon;

	this.animate = function (icon) {
		image.src = icon;

		chrome.browserAction.setIcon({path: icon});
		setTimeout(animateFlip, 1500);
	};

	var ease = function (x) {
		return (1 - Math.sin(Math.PI / 2 + x * Math.PI)) / 2;
	};

	var animateFlip = function () {
		rotation += 1 / animationFrames;
		drawIconAtRotation();
		if (rotation <= 1) {
			setTimeout(animateFlip, animationSpeed);
		} else {
			rotation = 0;
			drawIconAtRotation();
			chrome.browserAction.setIcon({path: defaultIcon});
		}
	};

	var drawIconAtRotation = function () {
		canvasContext.save();
		canvasContext.clearRect(0, 0, canvas.width, canvas.height);
		canvasContext.translate(
			Math.ceil(canvas.width / 2),
			Math.ceil(canvas.height / 2));
		canvasContext.rotate(2 * Math.PI * ease(rotation));
		canvasContext.drawImage(image,
			-Math.ceil(canvas.width / 2),
			-Math.ceil(canvas.height / 2));
		canvasContext.restore();

		chrome.browserAction.setIcon({imageData: canvasContext.getImageData(0, 0, canvas.width, canvas.height)});
	};

	canvasContext = canvas.getContext('2d');

	chrome.browserAction.setIcon({path: defaultIcon});
}

================================================
FILE: js/libs/Base64.js
================================================
/**
 *
 *  Base64 encode / decode
 *  http://www.webtoolkit.info/
 *
 **/

var Base64 = {

    // private property
    _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

    // public method for encoding
    encode: function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;

        input = Base64._utf8_encode(input);

        while (i < input.length) {

            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output = output +
                this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
                this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

        }

        return output;
    },

    // public method for decoding
    decode: function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {

            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }

        }

        output = Base64._utf8_decode(output);

        return output;

    },

    // private method for UTF-8 encoding
    _utf8_encode: function (string) {
        string = string.replace(/\r\n/g, "\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if ((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }

        return utftext;
    },

    // private method for UTF-8 decoding
    _utf8_decode: function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;

        while (i < utftext.length) {

            c = utftext.charCodeAt(i);

            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if ((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i + 1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i + 1);
                c3 = utftext.charCodeAt(i + 2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }

        }

        return string;
    }
};

================================================
FILE: js/notification.js
================================================
var contextsManager = new ContextsManager();
var extensionsManager = new ExtensionsManager();

$(document).ready(function () {
	//load translations
	$('[data-i18n]').each(function (i, item) {
		$(item).text(chrome.i18n.getMessage($(item).data('i18n')));
	});

	//gather information about extension that was just installed
	var extdata = chrome.extension.getBackgroundPage().getNewestExtension();

	if (!extdata || !extdata.name || !extdata.id) {
		window.close();
	} else {
		$('#extensionName').text(extdata.name);
		displayContexts();

		$('ul').bind("mousedown",function (e) {
			e.metaKey = true;
		}).selectable({
				filter: 'div',
				selected: function (event, ui) {
					$('#always_enabled').removeClass('ui-selected');
				}
			});

		$('#notification').bind("mousedown",function (e) {
			e.metaKey = true;
		}).selectable({
				filter: '#always_enabled',
				selected: function (event, ui) {
					$('div.ui-selected').removeClass('ui-selected');
				}
			});

		$('#new_context').bind("click", function () {
			var input = $('<input>').attr({
				type: 'text',
				class: 'text ui-widget-content ui-corner-all'
			}).keydown(function (event) {
				//wait for ENTER
				if (event.keyCode === 13) {
					event.preventDefault();
					var contextName = $(this).val(),
						contextImg = 'icons/dortmund/settings.png';

					//check if name provided isn't already in use
					if(contextsManager.contextExists(contextName) || contextName.length === 0) {
						$(this).addClass('ui-state-error');
						return false;
					}

					//create new context with default icon
					contextsManager.newContext(contextName, contextImg);
					//save configuration
					chrome.extension.getBackgroundPage().configUpdated();

					//append new context
					$('ul').append(createContextLi(contextName, contextName, contextImg)).find("div:last").addClass('ui-selected');
					//remove input field
					$(this).remove();
					//clear 'always enabled' selection
					$('#always_enabled').removeClass('ui-selected');
					//show 'new context' button
					$('#new_context').show();
				}
				$(this).removeClass('ui-state-error');
			});

			//show input and hide the button
			input.insertBefore($(this)).focus();
			$(this).hide();
		});

		$('button').button();

		$('#do_nothing').click(function () {
			window.close();
		});

		$('#save').click(function () {
			if ($('#always_enabled').is('.ui-selected')) {
				extensionsManager.init();
				extensionsManager.addExtensionToAlwaysEnabled(extdata.id);
				extensionsManager.save();

				chrome.extension.getBackgroundPage().configUpdated();
			} else {
				addToContexts(extdata.id, $('div.ui-selected'));
			}
			window.close();
		});
	}
});

function displayContexts() {
	//load and display available contexts
	var contexts = contextsManager.getContextsList();

	$.each(contexts, function (i, context) {
		$('ul').append(createContextLi(context.name, context.name, context.imgSrc));
	});
}

function createContextLi(name, title, imgSrc) {
	var img = $('<img>').attr('src', imgSrc);
	var span = $('<span>').append(title);

	var context = $('<div>').attr('class', 'list-context ui-widget-content ui-corner-all').append(img).append(span).data('contextName', name);

	return $('<li>').append(context);
}

//add extension to selected contexts
function addToContexts(extid, selectedContexts) {
	//reload contexts list - just in case
	contextsManager.init();

	if (selectedContexts.length > 0) {
		$.each($(selectedContexts), function (idx, contextElem) {
			contextsManager.addExtensionToContext($(contextElem).data('contextName'), extid);
		});

		contextsManager.save();
		chrome.extension.getBackgroundPage().configUpdated();
	}
}

================================================
FILE: js/options/dialogs.js
================================================
//open "new context" dialog
function openNewContextDialog() {
	var buttons = {};
	buttons[chrome.i18n.getMessage("create")] = function() {
				clearDialogErrors($(this));
				$(this).find('input, ul').removeClass("ui-state-error");

				var isValid = true;

				var contextName = $('#context-name').val();
				if(contextName.length == 0) {
					$('#context-name').addClass("ui-state-error");
					isValid = false;
					addDialogError($(this), chrome.i18n.getMessage("name_field_is_required"));
				}

				var contexts = $('.contextExtensions');
				for(var i=0; i<contexts.length; i++) {
					var context = contexts[i];
					if($(context).data('contextName') == contextName) {
						$('#context-name').addClass("ui-state-error");
						isValid = false;
						addDialogError($(this), chrome.i18n.getMessage("this_name_is_already_in_use"));
						break;
					}
				}

				var selectedIcon = $('#context-icons li.ui-selected img');
				if(selectedIcon.length == 0) {
					$('#context-icons').addClass("ui-state-error");
					isValid = false;
					addDialogError($(this), chrome.i18n.getMessage("pick_an_icon"));
				}
				
				var showIcon = $("#showExtensionIcon").is(':checked') ? 'show_extension' : 'show_context';

				if ( isValid ) {
					var context = newContext(contextName, selectedIcon.attr('src'), showIcon);
					$('#contexts').append(context);
					context.effect('highlight', {}, 'slow');
					$( this ).dialog( "close" );
					markDirty();
				}
			};

	buttons[chrome.i18n.getMessage("cancel")] = function() {
		$( this ).dialog( "close" );
	};

	$( '#new-context-form' )
		.dialog( "option", "title", chrome.i18n.getMessage("create_new_context") )
		.dialog( "option", "buttons", buttons)
		.dialog( "open" );
}

//open "edit context" dialog
function openEditContextDialog(context) {
	var contextName = context.find('.contextExtensions').data('contextName');
	var contextImg = context.find('.contextExtensions').data('contextImg');
	var contextIcon = context.find('.contextExtensions').data('contextIcon') || 'show_context';

	$( '#new-context-form' ).find('input[name=context-name]').val(contextName);
	$( '#new-context-form' ).find('img[src="'+contextImg+'"]').parent().addClass('ui-selected');
	$( '#new-context-form' ).find('#showExtensionIcon').prop('checked', (contextIcon === 'show_extension'));

	var buttons = {};
	buttons[chrome.i18n.getMessage("save")] = function() {
				clearDialogErrors($(this));
				$(this).find('input, ul').removeClass("ui-state-error");

				var isValid = true;

				var contextName = $('#context-name').val();
				if(contextName.length == 0) {
					$('#context-name').addClass("ui-state-error");
					isValid = false;
					addDialogError($(this), chrome.i18n.getMessage("name_field_is_required"));
				}

				var contexts = $('.contextExtensions');
				for(var i=0; i<contexts.length; i++) {
					var otherContext = contexts[i];
					if($(otherContext).closest('.context')[0] != context[0] && $(otherContext).data('contextName') == contextName) {
						$('#context-name').addClass("ui-state-error");
						isValid = false;
						addDialogError($(this), chrome.i18n.getMessage("this_name_is_already_in_use"));
						break;
					}
				}

				var selectedIcon = $('#context-icons li.ui-selected img');
				if(selectedIcon.length == 0) {
					$('#context-icons').addClass("ui-state-error");
					isValid = false;
					addDialogError($(this), chrome.i18n.getMessage("pick_an_icon"));
				}
				
				var showIcon = $("#showExtensionIcon").is(':checked') ? 'show_extension' : 'show_context';

				if ( isValid ) {
					context.find('.contextExtensions').data('contextName', contextName);
					context.find('.contextExtensions').data('contextImg', selectedIcon.attr('src'));
					context.find('.contextExtensions').data('contextIcon', showIcon);

					context.find('.contextTitle').text(contextName);
					context.find('.contextIcon').attr('src', selectedIcon.attr('src'));

					context.effect('highlight', {}, 'slow');

					$( this ).dialog( "close" );
					markDirty();
				}
			};

	buttons[chrome.i18n.getMessage("cancel")] = function() {
			$( this ).dialog( "close" );
		};

	$( '#new-context-form' )
		.dialog( "option", {
			title: chrome.i18n.getMessage("edit_context"),
			buttons: buttons,
			width: 370
		})
		.dialog( "open" );
}

//remove errors from edit/new context form
function clearDialogErrors(dialog) {
	$(dialog).find('.errors').empty().hide();
}

//append new context edit/new form error
function addDialogError(dialog, error) {
	var icon = $('<span />').attr('class', 'ui-icon ui-icon-info').attr('style', 'float: left; margin-right: .3em;');
	var p = $('<p />').append(icon).append(error);
	$(dialog).find('.errors').append(p).show();
}

//init basic dialog for editing / adding new contexts
function initNewContextDialog() {
	var icons = CONFIG.get("icons");
	for(var index in icons) {
		var iconName = icons[index];
		var iconImg = $('<img/>').attr('src', CONFIG.get("iconsPath") + iconName + '.png').attr('alt', iconName);
		var iconBox = $('<li/>').addClass('ui-widget-content').addClass('ui-corner-all').append(iconImg);

		$( "#context-icons" ).append(iconBox);
	}

	//selectable icons
	$( "#context-icons li" ).click(function() {
		$(this).addClass("ui-selected").siblings().removeClass("ui-selected");
	});

	$( "#new-context-form" ).dialog({
		autoOpen: false,
		resizable: false,
		width: 370,
		modal: true,
		close: function() {
			clearDialogErrors($(this));
			$(this).find('.ui-selected').removeClass("ui-selected");
			$(this).find('input:text').val( "" ).removeClass("ui-state-error");
			$(this).find('ul').removeClass( "ui-state-error" );
			$(this).find('#showExtensionIcon').prop('checked', false);
		}
	}).find('form').submit(function(){
		return false;
	});
}

function showErrorDialog(config) {
	var buttons = {};
	buttons[chrome.i18n.getMessage("close")] = function() {
		$( this ).dialog( "close" );
	};

	$( "#dialog-confirm" ).dialog({
		title: config.title,
		resizable: false,
		height: 200,
		modal: true,
		buttons: buttons
	}).find('span.dialog-content').text(config.content);
}

function importSuccessDialog(config) {
	var dialogElem = $( "#dialog-import-success" );
	var dialogHeight = 200;
	var buttons = {};
	buttons[chrome.i18n.getMessage("close")] = function() {
		$( this ).dialog( "close" );

		if(typeof config.callback == "function") {
			config.callback();
		}
	};

	if(config.missingExtensions.length > 0) {
		dialogElem.find('p:eq(1), ul').show();
		var extensionsList = dialogElem.find('ul');
		extensionsList.empty();

		$.each(config.missingExtensions, function(i, item){
			var extensionLink = $('<a>').text(item.name).attr('href', 'https://chrome.google.com/webstore/detail/' + item.id).attr('target', '_blank');

			extensionsList.append($('<li>').append(extensionLink));
		});

		dialogHeight = 'auto';
	} else {
		dialogElem.find('p:eq(1), ul').hide();
	}

	$( "#dialog-import-success" ).dialog({
		title: chrome.i18n.getMessage("successful_import"),
		resizable: false,
		height: dialogHeight,
		modal: true,
		buttons: buttons
	});
}

================================================
FILE: js/options/firstrun.js
================================================
var welcomeTab;
var welcomeScreenReady = false;

//display welcome screen and tutorial
function showWelcomeScreen() {
	welcomeTab = 0;
	$('#welcome li:gt(0)').hide();
	$('#welcome li:eq(0)').show();
	$('#welcome .previous').button('option', 'disabled', true);
	$('#welcome .next').show().button('option', 'disabled', false);
	$('#welcome .close').hide();

	if(!welcomeScreenReady) {
		initWelcomeScreen();
		welcomeScreenReady = true;
	}

	$('#welcome').dialog( "open" );
}

function initWelcomeScreen() {
	$('#welcome').show().dialog({
		title: chrome.i18n.getMessage("welcome") + '!',
		resizable: false,
		width: 510,
		modal: true
	});

	$('#welcome .next').click(function() {
		if(welcomeTab + 1 == $('#welcome li').length) {
			return;
		}

		welcomeTab++;

		if(welcomeTab + 1 == $('#welcome li').length) {
			$(this).button('option', 'disabled', true);
			$(this).hide();
			$('#welcome .close').show();
		}

		$('#welcome .previous').button('option', 'disabled', false);

		$('#welcome li').hide();
		$('#welcome li:eq(' + welcomeTab + ')').show();
	});

	$('#welcome .previous').click(function() {
		if(welcomeTab - 1 < 0) {
			return;
		}

		welcomeTab--;

		$('#welcome .next').show();
		$('#welcome .close').hide();

		if(welcomeTab - 1 < 0) {
			$(this).button('option', 'disabled', true);
		}

		$('#welcome .next').button('option', 'disabled', false);

		$('#welcome li').hide();
		$('#welcome li:eq(' + welcomeTab + ')').show();
	});

	$('#welcome .close').click(function() {
		$('#welcome').dialog( "close" );
	});
}

================================================
FILE: js/options/main.js
================================================
var extensionsManager;
var contextsManager;
var configurationBackupExporter = new ConfigurationBackupExporter();
var configurationBackupImporter = new ConfigurationBackupImporter();
var storageSync = new HugeStorageSync();

//display list of all extensions
function displayExtensions() {
	//get the processed list back from ExtensionsManager
	var extensionsList = extensionsManager.getExtensionsList();

	$('#extensions, #always_enabled_extensions').empty();

	for (var index in extensionsList) {
		var extension = extensionsList[index];

		var li = createExtensionLi(extension);

		if (extensionsManager.isAlwaysEnabled(extension.id)) {
			$('#always_enabled_extensions').append(li);
		} else {
			$('#extensions').append(li);
		}
	}

	$('#extensions li, #always_enabled_extensions li').draggable({
		zIndex: 1000,
		helper: 'clone',
		opacity: 0.75,
		revert: 'invalid'
	});
}

//create list element representing an extension
function createExtensionLi(extdata) {
	//use smallest extension icon if it exists
	var icon = (extdata.icons && extdata.icons.length) ? (extdata.icons[0].url) : ('icons/plugin.png');

	var img = $('<img>').attr('src', icon);
	var span = $('<span/>').addClass('extensionName').text(extdata.name);
	var removeImg = $('<span />').attr('class', 'ui-icon ui-icon-circle-close');
	var removeBtn = $('<div />').addClass('removeBtn').append(removeImg);
	var status = 'status-' + ((extdata.enabled == true) ? 'enabled' : 'disabled');
	var li = $('<li>').addClass('ui-widget-content').addClass('ui-corner-all ' + status).attr('data-extid', extdata.id).attr('data-exticon', icon).append(img).append(span).append(removeBtn);

	if (extdata.isApp) {
		li.addClass('app');

		//if apps support is disabled don't show them
		if (CONFIG.get('appsSupport') === 'false') {
			li.hide();
		}
	}

	return li;
}

//display available contexts
function displayContexts() {
	var contexts = contextsManager.getContextsList();

	$('#contexts').empty();

	for (var gindex in contexts) {
		var context = contexts[gindex];
		var contextObj = newContext(context.name, context.imgSrc, context.icon);

		var contextUl = contextObj.find('ul');

		for (var eindex in context.extensions) {
			var extension = context.extensions[eindex];
			var extData = extensionsManager.getExtensionData(extension.id);

			if (extData) {
				var extLi = createExtensionLi(extData);
				contextUl.append(extLi);
			}
		}

		$('#contexts').append(contextObj);
	}

	$('#contexts').sortable({
		forcePlaceholderSize: true,
		handle: '.contextGrip',
		placeholder: 'context ui-state-highlight',
		tolerance: 'pointer',
		change: function (event, ui) {
			markDirty();
		}
	});
}

//check if extension is already in given context
function isInContext(context, newExtension) {
	var extensions = context.find('li');
	var exists = false;
	var newExtId = newExtension.data('extid');

	$.each(extensions, function (i, extension) {
		if ($(extension).data('extid') == newExtId) {
			exists = true;
		}
	});

	return exists;
}

//create new list object representing context
function newContext(name, imgSrc, showIcon) {
	var contextImg = $('<img/>').addClass('contextIcon').attr('src', imgSrc);
	var contextSpan = $('<span/>').addClass('contextTitle').text(name);
	var contextIcon = (showIcon || false);
	var contextGrip = $('<div/>').attr('title', chrome.i18n.getMessage("move")).addClass('contextGrip').append(contextImg).append(contextSpan);
	var contextMenu = $('<div class="contextMenu">' +
		'<a href="#" class="contextDuplicate"><span class="ui-icon ui-icon-copy" title="' + chrome.i18n.getMessage("clone") + '"></span></a>' +
		'<a href="#" class="contextEdit"><span class="ui-icon ui-icon-wrench" title="' + chrome.i18n.getMessage("edit") + '"></span></a>' +
		'<a href="#" class="contextDelete"><span class="ui-icon ui-icon-closethick" title="' + chrome.i18n.getMessage("delete") + '"></span></a>' +
		'</div>');
	var contextUl = $('<ul>').addClass('contextExtensions').data('contextName', name).data('contextImg', imgSrc).data('contextIcon', contextIcon);
	var contextLi = $('<li>').addClass('ui-widget-content').addClass('ui-corner-all').addClass('context').append(contextGrip).append(contextMenu).append(contextUl);

	contextUl.sortable({
		placeholder: 'ui-widget-content ui-corner-all ui-state-highlight',
		forcePlaceholderSize: true,
		tolerance: 'pointer',
		revert: true,
		change: function () {
			markDirty();
		}
	});

	contextUl.droppable({
		activeClass: 'active',
		hoverClass: 'active_hover',
		accept: function (element) {
			return element.is('#extensions li') && !isInContext($(this), element);
		},
		drop: function (event, ui) {
			if (ui.draggable.parent().is("#extensions")) {
				var li = ui.draggable.clone();
				$(this).append(li);
			}

			$(this).sortable("refresh");

			markDirty();
		}
	});

	return contextLi;
}

function importConfiguration(configurationString) {
	var buttons = {};
	buttons[chrome.i18n.getMessage("import")] = function () {
		configurationBackupImporter.importConfig(configurationString, function (status, missingExtensions, errors) {
			if (status) {
				importSuccessDialog({
					missingExtensions: missingExtensions,
					callback: function () {
						loadConfiguration();
						$('#import_box').val('');
					}
				});
			} else {
				window.console.error(errors);

				showErrorDialog({
					title: chrome.i18n.getMessage("import_failed"),
					content: chrome.i18n.getMessage("configuration_string_is_invalid")
				});
			}
		});

		$(this).dialog("close");
	};
	buttons[chrome.i18n.getMessage("cancel")] = function () {
		$(this).dialog("close");
	};

	$("#dialog-confirm").dialog({
		title: chrome.i18n.getMessage("override_current_settings"),
		resizable: false,
		width: 300,
		height: 200,
		modal: true,
		buttons: buttons
	}).find('span.dialog-content').text(chrome.i18n.getMessage("confirm_configuration_import"));
}

//mark config as modified
function markDirty() {
	$("#save-button").button("option", "disabled", false);
	highlightUngrouped();
}

//mark config as saved
function markClean() {
	$("#save-button").button("option", "disabled", true);

	//generates current configuration string - used for import/export
	configurationBackupExporter.exportConfig(function (exportedConfig) {
		$('#export_box').val(exportedConfig);
	});
}

//save context data and additional options in localStorage
function save() {
	var contextsData = [];

	var contexts = $('.contextExtensions');
	$.each(contexts, function (i, context) {
		var contextName = $(context).data('contextName');
		var contextImg = $(context).data('contextImg');
		var contextIcon = $(context).data('contextIcon');
		var contextObj = {
			'name': contextName,
			'imgSrc': contextImg,
			'icon': contextIcon,
			'extensions': []
		};

		var extensions = $(context).find('li:visible');

		$.each(extensions, function (i, extension) {
			var extid = $(extension).data('extid');
			var exticon = $(extension).data('exticon');
			var extObj = {
				id: extid,
				icon: exticon
			};

			contextObj.extensions.push(extObj);
		});

		contextsData.push(contextObj);
	});

	localStorage.contexts = JSON.stringify(contextsData);

	var alwaysEnabledExtensionsData = [];
	var extensions = $('#always_enabled_extensions li');

	$.each(extensions, function (i, extension) {
		var extid = $(extension).data('extid');

		alwaysEnabledExtensionsData.push(extid);
	});

	extensionsManager.setAlwaysEnabledExtensionsIds(alwaysEnabledExtensionsData);
	localStorage.alwaysEnabledExtensions = JSON.stringify(alwaysEnabledExtensionsData);

	saveAdvancedOptions();

	chrome.extension.getBackgroundPage().configUpdated();
	markClean();
}

var advancedOptions = ['appsSupport', 'newExtensionAction', 'showLoadAllBtn', 'extensionEnableDelay'];

function saveAdvancedOptions() {
	for (var i in advancedOptions) {
		var option = advancedOptions[i];

		if ($('#' + option).is('[type=checkbox]')) {
			localStorage[option] = $('#' + option).is(':checked');
		} else {
			localStorage[option] = $('#' + option).val();
		}
	}
}

function displayAdvancedOptions() {
	for (var i in advancedOptions) {
		var option = advancedOptions[i];
		var $option = $('#' + option);

		if ($option.is('[type=checkbox]')) {
			if (CONFIG.get(option) === 'true') {
				$option.attr('checked', 'checked');
			} else {
				$option.removeAttr('checked');
			}
		} else if ($option.is('select')) {
			$option.find('option').removeAttr('selected');
			$option.find('option[value=' + CONFIG.get(option) + ']').attr('selected', 'selected');
		} else {
			$option.val(CONFIG.get(option));
		}
	}
}

//actions performed after config page is fully loaded
function pageLoaded() {
	$('#loader').slideUp('slow', function () {
		$('#content').slideDown('slow', function () {
			//display welcome screen if extension was just installed
			if (CONFIG.get('firstRun') == 'yes') {
				showWelcomeScreen();
				localStorage.firstRun = 'no';
			}
		});
	});
}

//highlights not grouped extensions inside 'Available extensions' box
function highlightUngrouped() {
	var enabled = $('#highlightUngrouped').is(':checked');

	//remove .ui-state-active class from all extensions in contexts, always-enabled box and available extensions box
	$('.extensions_list li.ui-state-active, .contextExtensions li.ui-state-active').removeClass('ui-state-active');

	if (enabled) {
		$.each($('#extensions li'), function (i, extensionElem) {
			var extid = $(extensionElem).data('extid');

			if ($('.context li[data-extid=' + extid + ']').length === 0) {
				$(extensionElem).addClass('ui-state-active');
			}
		});
	}
}

function loadConfiguration() {
	contextsManager = new ContextsManager();
	extensionsManager = new ExtensionsManager(function () {
		displayExtensions();
		displayContexts();
		displayAdvancedOptions();
		pageLoaded();
		if(localStorage.highlightUngroupedExtensions === 'true') {
			highlightUngrouped();
		}
		markClean();
	});
}

function loadTranslations() {
	$('[data-i18n]').each(function (i, item) {
		$(item).text(chrome.i18n.getMessage($(item).data('i18n')));
	});
}

$(document).ready(function () {
	loadConfiguration();
	loadTranslations();
	initNewContextDialog();

	//remove social icons if user is offline
	if(!navigator.onLine) {
		$('#social-buttons').empty();
	}

	$('button, input[type=submit], input[type=button]').button();

	$('.removeBtn').live('click', function () {
		$(this).closest('li').effect('slide', {mode: 'hide'}, 'normal', function () {
			$(this).remove();
			markDirty();
		});
	});

	$('#help-icon').click(function () {
		showWelcomeScreen();
	});

	$('.contextDelete').live('click', function () {
		var context = $(this).closest('.context');
		var buttons = {};
		buttons[chrome.i18n.getMessage("delete")] = function () {
			context.effect('puff', {}, 'slow', function () {
				$(this).remove();
				markDirty();
			});

			$(this).dialog("close");
		};
		buttons[chrome.i18n.getMessage("cancel")] = function () {
			$(this).dialog("close");
		};

		$("#dialog-confirm").dialog({
			title: chrome.i18n.getMessage("remove_context"),
			resizable: false,
			height: 200,
			modal: true,
			buttons: buttons
		}).find('span.dialog-content').text(chrome.i18n.getMessage("context_will_be_deleted"));

		return false;
	});

	$('.contextDuplicate').live('click', function () {
		var original = $(this).closest('.context');
		var contextsContainer = $('.contextExtensions');

		var oldImageSrc = original.find('.contextExtensions').data('contextImg');
		var oldName = original.find('.contextExtensions').data('contextName');
		var oldIcon = original.find('.contextExtensions').data('contextIcon');
		var newName;

		//generate new, unique name
		for (var j = 1; ; j++) {
			var isValid = true;
			var checkName = oldName + j;

			for (var i = 0; i < contextsContainer.length; i++) {
				var otherContext = contextsContainer[i];
				if ($(otherContext).data('contextName') == checkName) {
					isValid = false;
					break;
				}
			}

			if (isValid) {
				newName = checkName;
				break;
			}
		}

		var clone = newContext(newName, oldImageSrc, oldIcon);//create new context with same icon but new name
		clone.find('.contextExtensions').append(original.find('.contextExtensions li').clone());//copy extensions from original context to clone
		$('#contexts').append(clone);

		clone.effect('highlight', {}, 'slow');
		markDirty();

		return false;
	});

	$('.contextEdit').live('click', function () {
		openEditContextDialog($(this).closest('.context'));
		return false;
	});

	/* Additional options */
	$('#accordion').accordion({
		autoHeight: false,
		collapsible: true,
		active: false
	});

	$('#additional-options-panel').find('input, select, textarea').change(function () {
		markDirty();
	});

	$('#appsSupport').change(function () {
		if ($(this).is(':checked')) {
			$('li.app').effect('slide', {}, 'normal', markDirty);
		} else {
			$('li.app').effect('slide', {mode: 'hide'}, 'normal', markDirty);
		}
	});

	//moving extensions between 'available' section and 'always enabled' section
	$('#extensions').droppable({
		activeClass: 'active_dense',
		hoverClass: 'active_hover',
		accept: function (element) {
			return element.is('#always_enabled_extensions li');
		},
		drop: function (event, ui) {
			var li = ui.draggable.detach();
			$(this).append(li);

			//if extension was moved back from 'always enabled' box to 'available' box there may be some copies of this extension hidden in the contexts, show them
			$('.context li[data-extid=' + li.data('extid') + ']').effect('slide');

			markDirty();
		}
	});

	$('#always_enabled_extensions').droppable({
		activeClass: 'active_dense',
		hoverClass: 'active_hover',
		accept: function (element) {
			return element.is('#extensions li');
		},
		drop: function (event, ui) {
			var li = ui.draggable.detach();
			$(this).append(li);

			//HACK - contexts stay highlighted after object is dropped - AFAIK it is because draggable is detached not cloned
			$('.contextExtensions.active').removeClass('active');

			//remove this extension from all contexts as it is redundant there now
			$('.context li[data-extid=' + li.data('extid') + ']').effect('slide', {mode: 'hide'});

			markDirty();
		}
	});

	$('#highlightUngrouped').click(function () {
		highlightUngrouped();
		localStorage.highlightUngroupedExtensions = $(this).is(':checked') ? 'true' : 'false';
	});
	if(localStorage.highlightUngroupedExtensions === 'true') {
		$('#highlightUngrouped').attr('checked', 'checked');
	}

	$('#export_box, #import_box').click(function () {
		this.select();
	});

	$('#import_button').click(function () {
		importConfiguration($('#import_box').val());
		return false;
	});

	$('#chrome_sync_export_button').click(function(){
		var configurationString = $('#export_box').val();
		var $exportButton = $(this);
		var buttons = {};
		buttons[chrome.i18n.getMessage("save")] = function () {
			storageSync.set('configuration', configurationString, function() {
				var originalText = $exportButton.find('span').text();
				$exportButton.find('span').text(chrome.i18n.getMessage("saved"));
				$exportButton.effect('highlight', {}, 'slow');
				setTimeout(function() {
					$exportButton.find('span').text(originalText);
				}, 2500);
			});

			$(this).dialog("close");
		};
		buttons[chrome.i18n.getMessage("cancel")] = function () {
			$(this).dialog("close");
		};

		$("#dialog-confirm").dialog({
			title: chrome.i18n.getMessage("override_server_settings"),
			resizable: false,
			width: 300,
			height: 200,
			modal: true,
			buttons: buttons
		}).find('span.dialog-content').text(chrome.i18n.getMessage("confirm_chrome_sync_configuration_export"));
		return false;
	});

	$('#chrome_sync_import_button').click(function(){
		storageSync.get('configuration', function(value){
			importConfiguration(value);
		});
		return false;
	});

	$('#new-context-button').click(function () {
		openNewContextDialog();
	});
	$('#save-button').click(function () {
		save();
	});
});

================================================
FILE: js/popup.js
================================================
function createListOfContexts() {
	contextsManager.getContextsListWithStatuses(function(contexts){
		$('#contextsScreen ul').empty();

		contexts.forEach(function(context) {
			$('#contextsScreen ul').append(createContextLi(context.name, context.name, getContextIcon(context), context.status));
		});

		//create a context activating all extensions
		if(CONFIG.get('showLoadAllBtn') === 'true') {
			allBtn = createContextLi('all', chrome.i18n.getMessage("all_extensions"), 'icons/plugin.png');
			$('#contextsScreen ul').append(allBtn);
		}
	});
}

function createListOfExtensions(extid) {
	var context, extensions;

	if(extid) {
		context = contextsManager.getContext(extid);
		extensions = context.extensions;
	} else {
		extensions = extensionsManager.getExtensionsList();
	}

	$('#extensionsScreen ul > li:gt(0)').remove();
	for(var idx in extensions) {
		var extId = extensions[idx].id;
		var extension = extensionsManager.getExtensionData(extId);

		if(extension.isApp && CONFIG.get('appsSupport') !== 'true') {
			continue;
		}

		$('#extensionsScreen ul').append(createExtensionLi(extension));
	}
}

function createContextLi(name, title, imgSrc, status) {
	var img = $('<img>').attr('src', imgSrc);
	var span = $('<span>').append(title);
	var all = ((name == 'all') ? 'all' : 'single') + '-context';

	var activate = $("<div class='list-button activate ui-widget-content ui-corner-all'><span class='ui-icon ui-icon-plusthick'></span></div>");
	var deactivate = $("<div class='list-button deactivate ui-widget-content ui-corner-all'><span class='ui-icon ui-icon-minusthick'></span></div>");
	var showExtensions = $("<div class='list-button show-extensions ui-widget-content ui-corner-all'><span class='ui-icon ui-icon-triangle-1-e'></span></div>");

	var context = $('<div>').attr('class', 'list-context ui-widget-content ui-corner-all ' + all).append(img).append(span);

	var li = $('<li>')
		.addClass('clearfix')
		.append(context)
		.append(activate)
		.append(deactivate)
		.append(showExtensions)
		.data('contextName', name);

	if(status === 'enabled') {
		li.addClass('status-all');
	} else if(status === 'partial') {
		li.addClass('status-partial');
	}

	return li;
}

function createExtensionLi(extension) {
	var imgSrc = (extension.icons && extension.icons.length) ? (extension.icons[0].url) : ('icons/plugin.png');
	var img = $('<img>').attr('src', imgSrc);
	var span = $('<span>').addClass('extension-name').append(extension.name);

	var extensionDiv = $('<div>')
		.attr('class', 'list-item ui-widget-content ui-corner-all')
		.append(img)
		.append(span)
		.addClass(extension.enabled ? 'status-enabled' : 'status-disabled');

	var li = $('<li>')
		.addClass('clearfix')
		.append(extensionDiv)
		.data('extensionID', extension.id);

	return li;
}

function getContextIcon(context) {
	if (context.icon === 'show_extension' && context.extensions[0] && context.extensions[0].icon) {
		return context.extensions[0].icon;
	}

	return context.imgSrc;
}

var contextsManager = new ContextsManager();
var extensionsManager = new ExtensionsManager();
var currentContextName = null;
var blocked = false;
var allBtn;

$(document).ready(function(){
	//load translations
	$('[data-i18n]').each(function (i, item) {
		$(item).text(chrome.i18n.getMessage($(item).data('i18n')));
	});

	createListOfContexts();

	$('#contextsScreen').on('click', 'div.list-context, div.activate, div.deactivate', function(){
		//make sure that user won't change the context while other context is loading
		if(blocked) {
			return false;
		}
		blocked = true;

		$('div.list-context, div.list-button').not($(this)).addClass('ui-state-disabled');
		$(this).addClass('ui-state-active');

		var li = $(this).closest('li');
		var buttonClicked = 'switch';

		if($(this).is('.activate')) {
			buttonClicked = 'activate';
		} else if($(this).is('.deactivate')) {
			buttonClicked = 'deactivate';
		}

		if(allBtn && li[0] == allBtn[0]) {//all extensions button clicked
			if(buttonClicked != 'deactivate') {
				chrome.extension.getBackgroundPage().enableAllExtensions();
			} else {
				chrome.extension.getBackgroundPage().disableAllExtensions();
			}
		} else {
			if(buttonClicked == 'switch') {
				chrome.extension.getBackgroundPage().changeContext(li.data('contextName'));
			} else if(buttonClicked == 'activate') {
				chrome.extension.getBackgroundPage().activateContext(li.data('contextName'));
			} else if(buttonClicked == 'deactivate') {
				chrome.extension.getBackgroundPage().deactivateContext(li.data('contextName'));
			}
		}

		//small timeout before closing the popup
		setTimeout(function(){
			window.close();
		}, 500);

		return false;
	});

	$('#contextsScreen').on('click', 'div.show-extensions', function() {
		$('.screenContainer').addClass('showExtensions');
		var li = $(this).closest('li');

		if(allBtn && li[0] === allBtn[0]) { // 'all extensions' button clicked
			currentContextName = null;
			createListOfExtensions();
		} else {
			currentContextName = li.data('contextName');
			createListOfExtensions(currentContextName);
		}
	});

	$('.back-to-contexts').on('click', function() {
		$('.screenContainer').removeClass('showExtensions');
	});

	$('#extensionsScreen').on('click', 'li', function(){
		var li = $(this);
		var extension = extensionsManager.getExtensionData( li.data('extensionID') );

		if(!extension) {
			return;
		}

		extensionsManager.enableExtension(extension, !extension.enabled, function() {
			createListOfContexts();
			//reload extensions manager before updating list of extensions
			extensionsManager = new ExtensionsManager(function () {
				createListOfExtensions(currentContextName);
			});
		});
	});
});

================================================
FILE: manifest.json
================================================
{
   "name": "Context",
   "version": "0.414",
   "manifest_version": 2,
   "permissions": [ "management", "notifications", "tabs", "storage" ],
   "background": {
      "page": "background.html"
   },
   "options_page": "options.html",
   "browser_action": {
      "default_icon": "icons/context.png",
      "default_popup": "popup.html",
      "default_title": "Context"
   },
   "default_locale": "en",
   "description": "__MSG_application_description__",
   "icons": {
      "128": "icons/context-128.png",
      "19": "icons/context.png",
      "48": "icons/context-48.png",
      "64": "icons/context-64.png"
   },
  "content_security_policy": "script-src 'self' https://apis.google.com https://platform.twitter.com https://www.facebook.com; object-src 'self'"
}


================================================
FILE: notification.html
================================================
<html>
<head>
	<meta charset="utf-8">

	<title data-i18n="context_options"></title>
	<link rel="stylesheet" href="css/ui-lightness/jquery-ui-1.8.17.custom.css" type="text/css" />
	<link rel="stylesheet" href="css/main.css" type="text/css" />

	<script src="js/libs/jquery-1.7.1.min.js"></script>
	<script src="js/libs/jquery-ui-1.8.17.custom.min.js"></script>
	
	<script src="js/classes/Configuration.class.js"></script>
	<script src="js/classes/ExtensionsManager.class.js"></script>
	<script src="js/classes/ContextsManager.class.js"></script>

	<script src="js/notification.js"></script>
</head>
<body id='notification'>
	<p><span data-i18n="extension_installed_1"></span> "<span id='extensionName'></span>" <span data-i18n="extension_installed_2"></span>. <span data-i18n="add_to_contexts"></span>:</p>
	<ul class='simple-list'>
	</ul>
	<div id='new_context' class="inline-selectable list-context ui-widget-content ui-corner-all"><span class='ui-icon ui-icon-plusthick float-left'></span><span data-i18n="new_context"></span></div>
	<p><span data-i18n="or_add_it_to"></span>: <span id='always_enabled' class="inline-selectable ui-widget-content ui-corner-all" data-i18n="always_enabled_extensions"></span></p>
	<button id='save' data-i18n="save"></button>
	<button id='do_nothing' data-i18n="cancel"></button>
</body>
</html>

================================================
FILE: options.html
================================================
<html>
<head>
	<meta charset="utf-8">

	<title data-i18n="context_options"></title>
	<link rel="icon" type="image/png" href="icons/context_wrench.png">
	<link rel="stylesheet" href="css/ui-lightness/jquery-ui-1.8.17.custom.css" type="text/css"/>
	<link rel="stylesheet" href="css/main.css" type="text/css"/>

	<script src="js/libs/jquery-1.7.1.min.js"></script>
	<script src="js/libs/jquery-ui-1.8.17.custom.min.js"></script>
	<script src="js/libs/Base64.js"></script>

	<script src="js/classes/HugeStorageSync.class.js"></script>
	<script src="js/classes/Configuration.class.js"></script>
	<script src="js/classes/ExtensionsManager.class.js"></script>
	<script src="js/classes/ContextsManager.class.js"></script>
	<script src="js/classes/ConfigurationBackupExporter.class.js"></script>
	<script src="js/classes/ConfigurationBackupImporter.class.js"></script>

	<script src="js/options/main.js"></script>
	<script src="js/options/firstrun.js"></script>
	<script src="js/options/dialogs.js"></script>
</head>
<body>

<div class='wrapper'>
	<h1>Context <span data-i18n="options"></span></h1>

	<div id='loader'>
		<p><img src='other/flower.gif'/> <span data-i18n="extension_is_loading"></span></p>
	</div>

	<div id='content'>
		<div id='help-icon'><span class='ui-icon ui-icon-help'></span></div>

		<div class='ui-widget-content ui-corner-all' id='available_extensions_wrapper'>
			<h2 data-i18n="available_extensions"></h2>

			<div class='top-right-box ui-widget'>
				<input type='checkbox' id='highlightUngrouped'/> <label for='highlightUngrouped'
				                                                        data-i18n="highlight_ungrouped_extensions"></label>
			</div>
			<ul id="extensions" class='extensions_list clearfix'>
			</ul>
		</div>

		<div class='ui-widget-content ui-corner-all' id='always_enabled_extensions_wrapper'>
			<h2 data-i18n="always_enabled_extensions"></h2>
			<ul id="always_enabled_extensions" class='extensions_list clearfix'>
			</ul>
		</div>

		<ul id="contexts" class='clearfix'>
		</ul>

		<!-- FORMS AND DIALOGS -->
		<div id="new-context-form">
			<div class="ui-state-highlight ui-corner-all errors"></div>
			<form>
				<fieldset>
					<div class="dialog-label" data-i18n="name"></div>
					<input type="text" name="context-name" id="context-name"
					       class="text ui-widget-content ui-corner-all"/>

					<div class="dialog-label" data-i18n="icon"></div>
					<ul id='context-icons' class='clearfix'>
					</ul>

					<div class="dialog-label" data-i18n="additional_options"></div>
					<div><input type='checkbox' id='showExtensionIcon' /> <label
							for='showExtensionIcon' data-i18n="show_extension_icon"></label></div>
				</fieldset>
			</form>
		</div>
		<div id="dialog-confirm">
			<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span><span
					class="dialog-content"></span></p>
		</div>
		<div id="dialog-import-success">
			<p><span class="ui-icon ui-icon-info" style="float:left; margin:0 7px 20px 0;"></span><span
					data-i18n="configuration_was_imported_successfuly"></span></p>

			<p><span class="ui-icon ui-icon-info" style="float:left; margin:0 7px 20px 0;"></span><span
					data-i18n="some_extensions_were_ignored"></span></p>
			<ul>
			</ul>
		</div>
		<div id="accordion">
			<h3><a href="#" data-i18n="additional_options"></a></h3>

			<div id='additional-options-panel'>
				<ul>
					<li><input type='checkbox' id='appsSupport'/> <label for='appsSupport'
					                                                     data-i18n="enable_apps_support"></label></li>
					<li><select id='n
Download .txt
gitextract_q4srk3q8/

├── .editorconfig
├── .gitignore
├── Gruntfile.js
├── README.md
├── _locales/
│   ├── cleanup.php
│   ├── de/
│   │   └── messages.json
│   ├── en/
│   │   └── messages.json
│   ├── es/
│   │   └── messages.json
│   ├── fr/
│   │   └── messages.json
│   ├── it/
│   │   ├── description.txt
│   │   └── messages.json
│   ├── ja/
│   │   └── messages.json
│   ├── pl/
│   │   └── messages.json
│   ├── pt_BR/
│   │   └── messages.json
│   └── zh_CN/
│       └── messages.json
├── background.html
├── css/
│   ├── main.css
│   └── ui-lightness/
│       └── jquery-ui-1.8.17.custom.css
├── gfx/
│   ├── icon/
│   │   ├── ampoules/
│   │   │   ├── ampoules-icon-colors-condensed.xcf
│   │   │   └── ampoules-icon-colors.xcf
│   │   ├── context/
│   │   │   └── context.xcf
│   │   ├── intersec/
│   │   │   └── intersec-128.xcf
│   │   └── puzzle_next/
│   │       ├── puzzle_silver.xcf
│   │       ├── puzzle_silver_cog.xcf
│   │       └── puzzle_silver_cogs.xcf
│   ├── promo/
│   │   ├── context-128.xcf
│   │   ├── context-64.xcf
│   │   ├── large-promo-icons.xcf
│   │   ├── large-promo-less-icons.xcf
│   │   ├── large-promo.xcf
│   │   └── small-promo.xcf
│   ├── screenshots/
│   │   ├── step_1_en.xcf
│   │   ├── step_1_pl.xcf
│   │   ├── step_2_en.xcf
│   │   ├── step_2_pl.xcf
│   │   ├── step_3_en.xcf
│   │   ├── step_3_pl.xcf
│   │   ├── step_4_en.xcf
│   │   └── step_4_pl.xcf
│   └── webstore-scr/
│       ├── cn/
│       │   └── old_xcf/
│       │       ├── first.xcf
│       │       ├── grouping.xcf
│       │       └── popup.xcf
│       ├── first.xcf
│       ├── grouping.xcf
│       └── popup.xcf
├── js/
│   ├── background.js
│   ├── classes/
│   │   ├── Configuration.class.js
│   │   ├── ConfigurationBackupExporter.class.js
│   │   ├── ConfigurationBackupImporter.class.js
│   │   ├── ContextsManager.class.js
│   │   ├── ExtensionNotification.class.js
│   │   ├── ExtensionsManager.class.js
│   │   ├── HugeStorageSync.class.js
│   │   └── IconAnimation.class.js
│   ├── libs/
│   │   └── Base64.js
│   ├── notification.js
│   ├── options/
│   │   ├── dialogs.js
│   │   ├── firstrun.js
│   │   └── main.js
│   └── popup.js
├── manifest.json
├── notification.html
├── options.html
├── package.json
└── popup.html
Download .txt
SYMBOL INDEX (59 symbols across 15 files)

FILE: _locales/cleanup.php
  function json_readable_encode (line 12) | function json_readable_encode($in, $indent = 0) {
  class Translation (line 49) | class Translation {
    method __construct (line 53) | public function __construct($filePath) {
    method readJSON (line 63) | public function readJSON($json) {
    method hasMessage (line 83) | public function hasMessage($key) {
    method getMessage (line 87) | public function getMessage($key) {
    method getMessages (line 91) | public function getMessages() {
    method merge (line 95) | public function merge(Translation $baseTranslation) {
    method commit (line 115) | public function commit() {

FILE: js/background.js
  function init (line 5) | function init() {
  function reloadConfiguration (line 18) | function reloadConfiguration(callback) {
  function enableAllExtensions (line 26) | function enableAllExtensions() {
  function disableAllExtensions (line 32) | function disableAllExtensions() {
  function changeContext (line 38) | function changeContext(selectedContext) {
  function activateContext (line 75) | function activateContext(selectedContext) {
  function deactivateContext (line 107) | function deactivateContext(selectedContext) {
  function configUpdated (line 139) | function configUpdated() {
  function getNewestExtension (line 149) | function getNewestExtension() {
  function openConfig (line 230) | function openConfig() {

FILE: js/classes/Configuration.class.js
  function Configuration (line 1) | function Configuration() {

FILE: js/classes/ConfigurationBackupExporter.class.js
  function ConfigurationBackupExporter (line 1) | function ConfigurationBackupExporter() {

FILE: js/classes/ConfigurationBackupImporter.class.js
  function ConfigurationBackupImporter (line 1) | function ConfigurationBackupImporter() {

FILE: js/classes/ContextsManager.class.js
  function ContextsManager (line 1) | function ContextsManager() {

FILE: js/classes/ExtensionNotification.class.js
  function ExtensionNotification (line 1) | function ExtensionNotification(options) {

FILE: js/classes/ExtensionsManager.class.js
  function ExtensionsManager (line 1) | function ExtensionsManager(onLoadCallback) {

FILE: js/classes/HugeStorageSync.class.js
  function HugeStorageSync (line 1) | function HugeStorageSync() {

FILE: js/classes/IconAnimation.class.js
  function IconAnimation (line 1) | function IconAnimation(config) {

FILE: js/notification.js
  function displayContexts (line 97) | function displayContexts() {
  function createContextLi (line 106) | function createContextLi(name, title, imgSrc) {
  function addToContexts (line 116) | function addToContexts(extid, selectedContexts) {

FILE: js/options/dialogs.js
  function openNewContextDialog (line 2) | function openNewContextDialog() {
  function openEditContextDialog (line 57) | function openEditContextDialog(context) {
  function clearDialogErrors (line 129) | function clearDialogErrors(dialog) {
  function addDialogError (line 134) | function addDialogError(dialog, error) {
  function initNewContextDialog (line 141) | function initNewContextDialog() {
  function showErrorDialog (line 173) | function showErrorDialog(config) {
  function importSuccessDialog (line 188) | function importSuccessDialog(config) {

FILE: js/options/firstrun.js
  function showWelcomeScreen (line 5) | function showWelcomeScreen() {
  function initWelcomeScreen (line 21) | function initWelcomeScreen() {

FILE: js/options/main.js
  function displayExtensions (line 8) | function displayExtensions() {
  function createExtensionLi (line 35) | function createExtensionLi(extdata) {
  function displayContexts (line 59) | function displayContexts() {
  function isInContext (line 95) | function isInContext(context, newExtension) {
  function newContext (line 110) | function newContext(name, imgSrc, showIcon) {
  function importConfiguration (line 154) | function importConfiguration(configurationString) {
  function markDirty (line 193) | function markDirty() {
  function markClean (line 199) | function markClean() {
  function save (line 209) | function save() {
  function saveAdvancedOptions (line 262) | function saveAdvancedOptions() {
  function displayAdvancedOptions (line 274) | function displayAdvancedOptions() {
  function pageLoaded (line 295) | function pageLoaded() {
  function highlightUngrouped (line 308) | function highlightUngrouped() {
  function loadConfiguration (line 325) | function loadConfiguration() {
  function loadTranslations (line 339) | function loadTranslations() {

FILE: js/popup.js
  function createListOfContexts (line 1) | function createListOfContexts() {
  function createListOfExtensions (line 17) | function createListOfExtensions(extid) {
  function createContextLi (line 40) | function createContextLi(name, title, imgSrc, status) {
  function createExtensionLi (line 68) | function createExtensionLi(extension) {
  function getContextIcon (line 87) | function getContextIcon(context) {
Condensed preview — 65 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (226K chars).
[
  {
    "path": ".editorconfig",
    "chars": 298,
    "preview": "# EditorConfig is awesome: http://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with"
  },
  {
    "path": ".gitignore",
    "chars": 29,
    "preview": "*~\nnbproject\n.DS_Store\n.idea\n"
  },
  {
    "path": "Gruntfile.js",
    "chars": 1154,
    "preview": "module.exports = function(grunt) {\n\t\"use strict\";\n\n\tgrunt.initConfig({\n\t\tpkg: grunt.file.readJSON('package.json'),\n\t\tjsh"
  },
  {
    "path": "README.md",
    "chars": 2878,
    "preview": "Context\n======================\n\nChrome/Chromium extension that allows to sort other extensions into groups and easily sw"
  },
  {
    "path": "_locales/cleanup.php",
    "chars": 3875,
    "preview": "<?php\n/**\n* This script reads translation files and fixes them by:\n* - adding missing keys (basing on english translatio"
  },
  {
    "path": "_locales/de/messages.json",
    "chars": 7008,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"en\",\n        \"description\": \"There is build in @@_ui_locale variable but it s"
  },
  {
    "path": "_locales/en/messages.json",
    "chars": 7014,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"en\",\n        \"description\": \"There is build in @@_ui_locale variable but it s"
  },
  {
    "path": "_locales/es/messages.json",
    "chars": 7247,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"en\",\n        \"description\": \"There is build in @@_ui_locale variable but it s"
  },
  {
    "path": "_locales/fr/messages.json",
    "chars": 7551,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"en\",\n        \"description\": \"There is build in @@_ui_locale variable but it s"
  },
  {
    "path": "_locales/it/description.txt",
    "chars": 855,
    "preview": "Dai un'occhiata alle tue estensioni. Davvero le usi tutte quante e per tutto il tempo? Non credo. Lo sai che queste este"
  },
  {
    "path": "_locales/it/messages.json",
    "chars": 7407,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"en\",\n        \"description\": \"There is build in @@_ui_locale variable but it s"
  },
  {
    "path": "_locales/ja/messages.json",
    "chars": 6272,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"en\",\n        \"description\": \"There is build in @@_ui_locale variable but it s"
  },
  {
    "path": "_locales/pl/messages.json",
    "chars": 7203,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"pl\",\n        \"description\": \"Istnieje wbudowana zmienna @@_ui_locale która za"
  },
  {
    "path": "_locales/pt_BR/messages.json",
    "chars": 7263,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"en\",\n        \"description\": \"There is build in @@_ui_locale variable but it s"
  },
  {
    "path": "_locales/zh_CN/messages.json",
    "chars": 5626,
    "preview": "{\n    \"locale\": \n    {\n        \"message\": \"zh_CN\",\n        \"description\": \"浏览器内建 @@_ui_locale 变量,显示语言的变体如 en_GB 、en_US 等"
  },
  {
    "path": "background.html",
    "chars": 571,
    "preview": "<html>\n<head>\n\t<script src=\"js/libs/jquery-1.7.1.min.js\"></script>\n\n\t<script src=\"js/classes/Configuration.class.js\"></s"
  },
  {
    "path": "css/main.css",
    "chars": 16419,
    "preview": "/*\n * HTML5 Boilerplate\n *\n * What follows is the result of much research on cross-browser styling.\n * Credit left inlin"
  },
  {
    "path": "css/ui-lightness/jquery-ui-1.8.17.custom.css",
    "chars": 33406,
    "preview": "/*\n * jQuery UI CSS Framework 1.8.17\n *\n * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)\n * Dual licensed unde"
  },
  {
    "path": "js/background.js",
    "chars": 6476,
    "preview": "var contextsManager = new ContextsManager();\nvar extensionsManager = new ExtensionsManager();\nvar iconAnimation;\n\nfuncti"
  },
  {
    "path": "js/classes/Configuration.class.js",
    "chars": 901,
    "preview": "function Configuration() {\n\t\"use strict\";\n\tvar constants = {\n\t\ticonsPath: 'icons/dortmund/',\n\t\ticons: ['home', 'search',"
  },
  {
    "path": "js/classes/ConfigurationBackupExporter.class.js",
    "chars": 1925,
    "preview": "function ConfigurationBackupExporter() {\n\t\"use strict\";\n\tvar extensionsManager;\n\n\t/**\n\t * Creates dump (base64 encoded J"
  },
  {
    "path": "js/classes/ConfigurationBackupImporter.class.js",
    "chars": 5982,
    "preview": "function ConfigurationBackupImporter() {\n\t\"use strict\";\n\t/**\n\t * Array of errors that occurred during last import.\n\t * @"
  },
  {
    "path": "js/classes/ContextsManager.class.js",
    "chars": 4622,
    "preview": "function ContextsManager() {\n\t\"use strict\";\n\tvar that = this;\n\t/**\n\t * List of all contexts.\n\t * @type {Array.<Object>}\n"
  },
  {
    "path": "js/classes/ExtensionNotification.class.js",
    "chars": 1096,
    "preview": "function ExtensionNotification(options) {\n\t\"use strict\";\n\tvar useChromeNotifications = (chrome && chrome.notifications);"
  },
  {
    "path": "js/classes/ExtensionsManager.class.js",
    "chars": 5402,
    "preview": "function ExtensionsManager(onLoadCallback) {\n\t\"use strict\";\n\tvar that = this;\n\t/**\n\t * List of all installed extensions."
  },
  {
    "path": "js/classes/HugeStorageSync.class.js",
    "chars": 2013,
    "preview": "function HugeStorageSync() {\n\t\"use strict\";\n\n\tfunction getCacheKey(key, i) {\n\t\treturn (i === 0) ? key : key + \"_\" + i;\n\t"
  },
  {
    "path": "js/classes/IconAnimation.class.js",
    "chars": 1341,
    "preview": "function IconAnimation(config) {\n\t\"use strict\";\n\tvar animationFrames = 36,\n\t\tanimationSpeed = 10,//ms\n\t\trotation = 0,\n\t\t"
  },
  {
    "path": "js/libs/Base64.js",
    "chars": 3765,
    "preview": "/**\n *\n *  Base64 encode / decode\n *  http://www.webtoolkit.info/\n *\n **/\n\nvar Base64 = {\n\n    // private property\n    _"
  },
  {
    "path": "js/notification.js",
    "chars": 3669,
    "preview": "var contextsManager = new ContextsManager();\nvar extensionsManager = new ExtensionsManager();\n\n$(document).ready(functio"
  },
  {
    "path": "js/options/dialogs.js",
    "chars": 7058,
    "preview": "//open \"new context\" dialog\nfunction openNewContextDialog() {\n\tvar buttons = {};\n\tbuttons[chrome.i18n.getMessage(\"create"
  },
  {
    "path": "js/options/firstrun.js",
    "chars": 1534,
    "preview": "var welcomeTab;\nvar welcomeScreenReady = false;\n\n//display welcome screen and tutorial\nfunction showWelcomeScreen() {\n\tw"
  },
  {
    "path": "js/options/main.js",
    "chars": 15893,
    "preview": "var extensionsManager;\nvar contextsManager;\nvar configurationBackupExporter = new ConfigurationBackupExporter();\nvar con"
  },
  {
    "path": "js/popup.js",
    "chars": 5658,
    "preview": "function createListOfContexts() {\n\tcontextsManager.getContextsListWithStatuses(function(contexts){\n\t\t$('#contextsScreen "
  },
  {
    "path": "manifest.json",
    "chars": 769,
    "preview": "{\n   \"name\": \"Context\",\n   \"version\": \"0.414\",\n   \"manifest_version\": 2,\n   \"permissions\": [ \"management\", \"notification"
  },
  {
    "path": "notification.html",
    "chars": 1328,
    "preview": "<html>\n<head>\n\t<meta charset=\"utf-8\">\n\n\t<title data-i18n=\"context_options\"></title>\n\t<link rel=\"stylesheet\" href=\"css/ui"
  },
  {
    "path": "options.html",
    "chars": 8665,
    "preview": "<html>\n<head>\n\t<meta charset=\"utf-8\">\n\n\t<title data-i18n=\"context_options\"></title>\n\t<link rel=\"icon\" type=\"image/png\" h"
  },
  {
    "path": "package.json",
    "chars": 621,
    "preview": "{\n\t\"name\": \"Context\",\n\t\"version\": \"0.414.0\",\n\t\"description\": \"Sort extensions into groups and easily switch between them"
  },
  {
    "path": "popup.html",
    "chars": 947,
    "preview": "<html>\n<head>\n\t<meta charset=\"utf-8\">\n\n\t<link rel=\"stylesheet\" href=\"css/ui-lightness/jquery-ui-1.8.17.custom.css\" type="
  }
]

// ... and 27 more files (download for full content)

About this extraction

This page contains the full source code of the kdzwinel/Context GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 65 files (19.7 MB), approximately 56.0k tokens, and a symbol index with 59 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!