diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af79d2d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +unused \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG new file mode 100755 index 0000000..f13b37a --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,114 @@ +1.1.7: + *Fixed bug where packaged apps would not open + +1.1.6: + *Fixed bug where Chrome Web Store wouldn't display the name of the extension when in French + +1.1.5: + *Fixed bug in Chrome 27+ where Settings icon would not load chrome://settings + +1.1.4: + *Fixed bugs with adding a web clip with no title. + *Fixed FAQ about installing Launchpage to include the actual URL. + +1.1.1: + *Fixed bug with deprecated BlobBuilder API which prevented adding web clips + *Added detection of Chromium so that it replaces Chrome with Chromium in relevant messages + *Bug fixes + +1.1: + *Added ability to save webpages to the home screen + *Improved screen reader compatibility + *Added a list of contributors + *Bug fixes + +1.0.1: + *Upgraded to extension manifest version 2 + *Bug fixes + +1.0: + *Tweaked background selection grid display issues + *Added ability to delete backgrounds from the list + *Removed French localization from the package until it's up to par + +0.4.1: + *Now using Lucida Grande as the default font to integrate better with Chrome + *Added dominant background color detection (auto-adjust color scheme to match the background image) + *Added listbox control to select background instead of radio buttons + *Fixed text shadows on icons with long names from being cut off on the ends + *Added code to automatically apply gradient to infobar based on specified color + +0.4: + *Completely reworked background code + *Now using filesystem persistent storage instead of localStorage + *Fixed limited background size error + *Fixed options page only displaying 1 custom background at a time + +0.3.1: + *UI adjustments + *Improved accessibility + *Added Help page to Options + *Reduced memory usage + *Improved load speed for background images + *Improved overall load speed + *Optimized icon drawing algorithm + *Added HTML5 application cache + *Press Ctrl+Shift+J to see launcher load time + *Added highlighting of offline apps when the user goes offline + +0.3: + *Enabled Launchpage options page + *Added option to set a background + *Optimized icon drawing algorithm + *Drastically improved load speed by running in the background + *Fixed drag-and-drop to make the icon being dragged become transparent + *Improved French localization + *Renamed Preferences icon to Settings on all platforms + +0.2.2: + *Fixed the Options icon from failing to load Chrome's options on Windows + *Fixed the Preferences icon to make it labeled Options on Windows + *Fixed the window title from flashing on load + *Added a box shadow for the context menu + *Removed unused code + +0.2.1: + *Updated icons + +0.2: + *Fixed drag and drop + *Added persistent reordering of icons + +0.1.6: + *Completely restyled context menu + +0.1.5: + *Tweaked context menu + *Added uninstall prompt + *Added a simple French translation + +0.1.4: + *Added basic drag and drop of icons (not reordering yet) + *Added target-type-sensitive context menu + *Removed the search box + +0.1.3: + *Tweaked search algorithm + *Added minor search UX improvements + +0.1.2: + *Added localization (but English is the only language so far) + +0.1.1: + *Added ability to search the web + +0.1.0: + *First usable prototype + *Added search box + +0.0.5: + *Fixed several bugs + *Added more advanced styling & fluid grid layout + +0.0.1: + *Working concept diff --git a/_locales/en/messages.json b/_locales/en/messages.json new file mode 100755 index 0000000..ee41835 --- /dev/null +++ b/_locales/en/messages.json @@ -0,0 +1,286 @@ +{ + "extName": { + "message": "Launchpage", + "description": "The name of the extension" + }, + "extDescription": { + "message": "An aesthetic app launcher for the new tab page", + "description": "The description of the extension" + }, + "infobarNoApps": { + "message": "You don't have any apps. Click the Chrome Web Store icon below to download apps.", + "description": "Warn the user that they don't have any apps" + }, + "infobarOffline": { + "message": "You are currently offline. Apps that work without Internet access have been highlighted.", + "description": "Tell the user they are offline and why their offline apps are highlighted" + }, + "infobarClose": { + "message": "Close", + "description": "Let the user close the infobar" + }, + "iconSettings": { + "message": "Settings", + "description": "The name of the Chrome Settings icon" + }, + "iconSettingsDescription": { + "message": "Change $APPNAME$'s settings", + "description": "The description of the Settings icon", + "placeholders": { + "appName": { + "content": "$1", + "example": "Chromium" + } + } + }, + "iconWebStore": { + "message": "Chrome Web Store", + "description": "Chrome Web Store icon" + }, + "iconWebStoreDescription": { + "message": "Discover great apps, games, extensions and themes for Google Chrome.", + "description": "The description of the Chrome Web Store icon" + }, + "buttonCancel": { + "message": "Cancel", + "description": "Cancel button" + }, + "buttonUninstall": { + "message": "Uninstall", + "description": "Button to uninstall an app" + }, + "uninstallPageTitle": { + "message": "Confirm Uninstallation", + "description": "The title of the Uninstall dialog" + }, + "uninstallApp": { + "message": "Uninstall \"$APP$\"?", + "description": "Ask the user to confirm uninstalling an app", + "placeholders": { + "app": { + "content": "$1", + "example": "Angry Birds" + } + } + }, + "remove": { + "message": "Remove from $APPNAME$", + "description": "The context menu item that uninstalls an app", + "placeholders": { + "appName": { + "content": "$1", + "example": "Chromium" + } + } + }, + "buttonRemove": { + "message": "Remove", + "description": "Button to remove a web clip" + }, + "removePageTitle": { + "message": "Confirm Removal", + "description": "The title of the Remove Web Clip dialog" + }, + "removeWebClipMessage": { + "message": "Remove \"$APP$\"?", + "description": "Ask the user to confirm removing a web clip", + "placeholders": { + "app": { + "content": "$1", + "example": "Launchpage - Chrome Web Store" + } + } + }, + "removeWebClip": { + "message": "Remove Web Clip", + "description": "The context menu item that removes a web clip" + }, + "buttonAdd": { + "message": "Add", + "description": "Button to add website to home screen via page action" + }, + "addWebClipHeading": { + "message": "Add to home screen", + "description": "Heading in page action popup" + }, + "addWebClipDescription": { + "message": "An icon will be added to your home screen so you can quickly access this web site.", + "description": "Description in page action popup" + }, + "manageExtensions": { + "message": "Manage extensions...", + "description": "The context menu item that goes to Chrome's extension settings" + }, + "options": { + "message": "Options", + "description": "The context menu item for an app's Options" + }, + "optionsSearchField": { + "message": "Search options", + "description": "The placeholder for the search box on the Options page" + }, + "optionsBasics": { + "message": "Basics", + "description": "The Basics tab in the Options page" + }, + "optionsHelp": { + "message": "Help", + "description": "The Help tab in the Options page" + }, + "optionsGetHelp": { + "message": "Get Help", + "description": "The Get Help section in the Options page" + }, + "optionsHelpButton": { + "message": "Get help using Launchpage", + "description": "The Help button in the Options page" + }, + "optionsReportProblem": { + "message": "Report a problem", + "description": "The Report Problem button in the Options page" + }, + "optionsAbout": { + "message": "About Launchpage", + "description": "The About section in the Options page" + }, + "optionsVersion": { + "message": "Version $VERSION$", + "description": "The version number in the Options page", + "placeholders": { + "version": { + "content": "$1", + "example": "1.0" + } + } + }, + "optionsCopyright": { + "message": "Copyright © $YEAR$ Alex Cordonnier. All Rights Reserved.", + "description": "The copyright notice in the Options page", + "placeholders": { + "year": { + "content": "$1", + "example": "2012" + } + } + }, + "optionsBackground": { + "message": "Background", + "description": "The Background section in the Options page" + }, + "optionsBackgroundNotice": { + "message": "Note: Using a high-resolution background will greatly reduce the speed of the extension. Please don't use an image larger than your monitor.", + "description": "Warn the user about the speed costs of high-resolution backgrounds" + }, + "chameleonBackground": { + "message": "Change the theme colors based on my background", + "description": "Whether to change the color palette automatically" + }, + "optionsPageAction": { + "message": "Page Action", + "description": "The Page Action section in the Options page" + }, + "usePageAction": { + "message": "Display an icon in the address bar so I can add pages to the home screen", + "description": "Whether to display the page action in the address bar" + }, + "optionDefault": { + "message": "Default", + "description": "The default option" + }, + "contributors": { + "message": "Contributors", + "description": "The link to the list of contributors" + }, + "contribDevelopers": { + "message": "Developers", + "description": "The heading for the contributor list of developers" + }, + "contribTesters": { + "message": "Beta testers", + "description": "The heading for the contributor list of beta testers" + }, + "contribTranslators": { + "message": "Translators", + "description": "The heading for the contributor list of translators" + }, + "helpHeading": { + "message": "Launchpage Help", + "description": "The heading for the Help page" + }, + "faqHeading": { + "message": "Frequently Asked Questions", + "description": "The heading for the FAQ section on the Help page" + }, + "faqInstallQ": { + "message": "Q: How do I install Launchpage?", + "description": "How to install Launchpage" + }, + "faqInstallA": { + "message": "A: Go to https://chrome.google.com/webstore/detail/launchpage/bkdpdcgcbkkohcelcibdenakcngkmamg and click Add to Chrome to install Launchpage.", + "description": "How to install Launchpage" + }, + "faqOpenQ": { + "message": "Q: How do I open Launchpage?", + "description": "How to open Launchpage" + }, + "faqOpenA": { + "message": "A: Just open a new tab after installing Launchpage, and your home screen will show up automatically.", + "description": "How to open Launchpage" + }, + "faqOpenAppQ": { + "message": "Q: How do I open an app?", + "description": "How to open an app" + }, + "faqOpenAppA": { + "message": "A: From a new tab, click on the icon of the app you want to launch.", + "description": "How to open an app" + }, + "faqRearrangeQ": { + "message": "Q: How do rearrange my apps?", + "description": "How to rearrange apps" + }, + "faqRearrangeA": { + "message": "A: From a new tab, hold down the mouse button and drag the app you want to move over another app.", + "description": "How to rearrange apps" + }, + "faqOptionsQ": { + "message": "Q: How do I set Launchpage options?", + "description": "How to set options" + }, + "faqOptionsA": { + "message": "A: From a new tab, right click on any empty space and click Options.", + "description": "How to set options" + }, + "faqBackgroundQ": { + "message": "Q: How do I change the background?", + "description": "How to choose a background" + }, + "faqBackgroundA": { + "message": "A: Go to the Options page (see above) and make sure you are on the Basics tab. Then, in the Background section, click Choose File.", + "description": "How to choose a background" + }, + "faqAddWebClipQ": { + "message": "Q: How do I add a web page to my home screen?", + "description": "How to add a web clip" + }, + "faqAddWebClipA": { + "message": "A: From most web pages, you can click the Launchpage icon on the right side of the address bar and click Add.", + "description": "How to add a web clip" + }, + "faqNewFeaturesQ": { + "message": "Q: When will you add feature X?", + "description": "How to request features" + }, + "faqNewFeaturesA": { + "message": "A: I am a student and cannot develop Launchpage full-time. However, I will add features on a priority basis. To request a feature, please contact me at https://chrome.google.com/webstore/support/bkdpdcgcbkkohcelcibdenakcngkmamg#feature", + "description": "How to request features" + }, + "faqMoreHelpQ": { + "message": "Q: I still need help.", + "description": "How to contact for more help" + }, + "faqMoreHelpA": { + "message": "A: You can contact me via https://chrome.google.com/webstore/support/bkdpdcgcbkkohcelcibdenakcngkmamg#question if you need more help, and I will try to respond in a timely manner.", + "description": "How to contact for more help" + } +} diff --git a/_locales/en_GB/messages.json b/_locales/en_GB/messages.json new file mode 100644 index 0000000..8084f9b --- /dev/null +++ b/_locales/en_GB/messages.json @@ -0,0 +1,6 @@ +{ + "chameleonBackground": { + "message": "Change the theme colours based on my background", + "description": "Whether to change the color palette automatically" + } +} diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json new file mode 100644 index 0000000..54822c6 --- /dev/null +++ b/_locales/fr/messages.json @@ -0,0 +1,282 @@ +{ + "extName": { + "message": "Launchpage", + "description": "Le nom de l'extension" + }, + "extDescription": { + "message": "Un lanceur esthétiques d'applications de la page nouvel onglet", + "description": "La description de l'extension" + }, + "infobarNoApps": { + "message": "Vous n'avez pas des applications. Cliquez sur l'icône Chrome Web Store ci-dessous pour télécharger des applications.", + "description": "Avertir à l'utilisateur qu'il n'ont pas les applications" + }, + "infobarOffline": { + "message": "Vous êtes actuellement déconnecté de l'Internet. Apps qui fonctionnent sans accès à Internet ont été mis en évidence.", + "description": "Dites à l'utilisateur, ils sont hors ligne et pourquoi leurs applications en mode hors connexion sont mis en évidence" + }, + "infobarClose": { + "message": "Fermer", + "description": "Laissez l'utilisateur ferme la barre d'informations" + }, + "iconSettings": { + "message": "Paramètres", + "description": "Le nom de l'icône Chrome Paramètres" + }, + "iconSettingsDescription": { + "message": "Modifiez les paramètres de $APPNAME$", + "description": "La description de l'icône Chrome Paramètres", + "placeholders": { + "appName": { + "content": "$1", + "example": "Chromium" + } + } + }, + "iconWebStore": { + "message": "Chrome Web Store", + "description": "Chrome Web Store icône" + }, + "iconWebStoreDescription": { + "message": "Découvrez des applications, jeux, extensions et thèmes exceptionnels pour Google Chrome.", + "description": "La description du Chrome Web Store icône" + }, + "buttonCancel": { + "message": "Annuler", + "description": "Le bouton pour annuler" + }, + "buttonUninstall": { + "message": "Désinstaller", + "description": "Bouton pour désinstaller une application" + }, + "uninstallPageTitle": { + "message": "Confirmer la suppression", + "description": "Le titre de la boîte de dialogue Désinstaller" + }, + "uninstallApp": { + "message": "Déinstaller « $APP$ » ?", + "description": "Demandez à l'utilisateur de confirmer la désinstallation d'une application", + "placeholders": { + "app": { + "content": "$1", + "example": "Angry Birds" + } + } + }, + "remove": { + "message": "Supprimer de $APPNAME$", + "description": "Le context menu item qui désinstalle une application", + "placeholders": { + "appName": { + "content": "$1", + "example": "Chromium" + } + } + }, + "buttonRemove": { + "message": "Supprimer", + "description": "Bouton pour supprimer un clip web" + }, + "removePageTitle": { + "message": "Confirmer la suppression", + "description": "Le titre de la boîte de dialogue Supprimer Web Clip" + }, + "removeWebClipMessage": { + "message": "Supprimer « $APP$ » ?", + "description": "Demandez à l'utilisateur de confirmer la suppression d'un clip web", + "placeholders": { + "app": { + "content": "$1", + "example": "Launchpage - Chrome Web Store" + } + } + }, + "removeWebClip": { + "message": "Supprimer Web Clip", + "description": "Le context menu item qui enlève un clip web" + }, + "buttonAdd": { + "message": "Ajouter", + "description": "Bouton pour ajouter le site Web à l'écran d'accueil via l'action de page" + }, + "addWebClipHeading": { + "message": "Ajouter à l'écran d'accueil", + "description": "Titre de l'action la page popup" + }, + "addWebClipDescription": { + "message": "Une icône sera ajoutée à l'écran d'accueil pour un accès immédiat à ce site web.", + "description": "Description de l'action la page popup" + }, + "manageExtensions": { + "message": "Gérer les extensions...", + "description": "Le context menu item qui va à paramètres d'extension de Chrome" + }, + "options": { + "message": "Options", + "description": "Le context menu item pour les options d'une application" + }, + "optionsSearchField": { + "message": "Rechercher", + "description": "L'espace réservé pour le champ de recherche sur la page Options" + }, + "optionsBasics": { + "message": "Options de base", + "description": "L'onglet Général dans la page Options" + }, + "optionsHelp": { + "message": "Aide", + "description": "L'onglet Aide dans la page Options" + }, + "optionsGetHelp": { + "message": "Obtenir de l'aide", + "description": "La section Obtenir de l'aide dans la page Options" + }, + "optionsHelpButton": { + "message": "Obtenir de l'aide sur l'utilisation de Launchpage", + "description": "Le bouton Aide dans la page Options" + }, + "optionsReportProblem": { + "message": "Signaler un problème", + "description": "Le bouton Signaler un problème dans la page Options" + }, + "optionsAbout": { + "message": "À propos", + "description": "La section À propos de Launchpage dans la page Options" + }, + "optionsVersion": { + "message": "Version $VERSION$", + "description": "Le numéro de version dans la page Options", + "placeholders": { + "version": { + "content": "$1", + "example": "1.0" + } + } + }, + "optionsCopyright": { + "message": "Copyright © $YEAR$ Alex Cordonnier. Tous droits réservés.", + "description": "L'avis de copyright dans la page Options", + "placeholders": { + "year": { + "content": "$1", + "example": "2012" + } + } + }, + "optionsBackground": { + "message": "Fond d'écran", + "description": "La section fond d'écran dans la page Options" + }, + "chameleonBackground": { + "message": "Changer les couleurs du thème sur la base de mon expérience", + "description": "Faut-il modifier la palette de couleurs automatiquement" + }, + "optionsPageAction": { + "message": "Action de la page", + "description": "La section Action de page dans la page Options" + }, + "usePageAction": { + "message": "Afficher une icône dans la barre d'adresse afin que je puisse ajouter des pages à l'écran d'accueil", + "description": "Que ce soit pour afficher l'action de page dans la barre d'adresse" + }, + "optionDefault": { + "message": "Défaut", + "description": "L'option par défaut" + }, + "contributors": { + "message": "Contributeurs", + "description": "Le lien vers la liste des contributeurs" + }, + "contribDevelopers": { + "message": "Développeurs", + "description": "Le titre de la liste contributeur de développeurs" + }, + "contribTesters": { + "message": "Bêta-testeurs", + "description": "Le titre de la liste contributeur de bêta-testeurs" + }, + "contribTranslators": { + "message": "Traducteurs", + "description": "Le titre de la liste contributeur de traducteurs" + }, + "helpHeading": { + "message": "Aide de Launchpage", + "description": "Le titre de la page d'aide" + }, + "faqHeading": { + "message": "Foire Aux Questions", + "description": "Le titre de la section FAQ sur la page d'aide" + }, + "faqInstallQ": { + "message": "Q: Comment puis-j'installer Launchpage?", + "description": "Comment faire pour installer Launchpage" + }, + "faqInstallA": { + "message": "A: Aller à https://chrome.google.com/webstore/detail/launchpage/bkdpdcgcbkkohcelcibdenakcngkmamg et cliquez sur Ajouter à Chrome pour installer Launchpage.", + "description": "Comment faire pour installer Launchpage" + }, + "faqOpenQ": { + "message": "Q: Comment puis-je ouvrir Launchpage?", + "description": "Comment ouvrir Launchpage" + }, + "faqOpenA": { + "message": "A: Il suffit d'ouvrir un nouvel onglet après avoir installé Launchpage, et votre écran d'accueil apparaîtra automatiquement.", + "description": "Comment ouvrir Launchpage" + }, + "faqOpenAppQ": { + "message": "Q: Comment puis-je ouvrir une application?", + "description": "Comment faire pour ouvrir une application" + }, + "faqOpenAppA": { + "message": "A: D'un nouvel onglet, cliquez sur l'icône de l'application que vous souhaitez ouvrir.", + "description": "Comment faire pour ouvrir une application" + }, + "faqRearrangeQ": { + "message": "Q: Comment puis-réorganiser mes applications?", + "description": "Comment réorganiser les applications" + }, + "faqRearrangeA": { + "message": "A: D'un nouvel onglet, maintenez enfoncé le bouton de la souris et faites glisser l'application que vous souhaitez déplacer sur une autre application.", + "description": "Comment réorganiser les applications" + }, + "faqOptionsQ": { + "message": "Q: Comment puis-je définir des options Launchpage?", + "description": "Comment définir les options" + }, + "faqOptionsA": { + "message": "A: D'un nouvel onglet, faites un clic droit sur n'importe quel espace vide et cliquez sur Options.", + "description": "Comment définir les options" + }, + "faqBackgroundQ": { + "message": "Q: Comment puis-je changer le fond d'écran?", + "description": "Comment choisir un arrière-plan" + }, + "faqBackgroundA": { + "message": "A: Aller à la page Options (voir ci-dessus) et assurez-vous que vous êtes dans l'onglet Général puis, dans la section Contexte, cliquez sur Choisissez un fichier.", + "description": "Comment choisir un arrière-plan" + }, + "faqAddWebClipQ": { + "message": "Q: Comment puis-je ajouter une page Web à l'écran d'accueil?", + "description": "Comment ajouter un clip web" + }, + "faqAddWebClipA": { + "message": "A: De la plupart des pages Web, vous pouvez cliquer sur l'icône Launchpage sur le côté droit de la barre d'adresse et cliquez sur Ajouter.", + "description": "Comment ajouter un clip web" + }, + "faqNewFeaturesQ": { + "message": "Q: Quand vous ajoutez la caractéristique « X » ?", + "description": "Comment faire pour demander des fonctions" + }, + "faqNewFeaturesA": { + "message": "A: Je suis un étudiant et ne peut se développer Launchpage à temps plein. Cependant, je vais ajouter des fonctionnalités sur une base prioritaire. Pour demander une fonctionnalité, s'il vous plaît me contacter à https://chrome.google.com/webstore/support/bkdpdcgcbkkohcelcibdenakcngkmamg#feature", + "description": "Comment faire pour demander des fonctions" + }, + "faqMoreHelpQ": { + "message": "Q: J'ai encore besoin d'aide.", + "description": "Comment contacter pour plus d'aide" + }, + "faqMoreHelpA": { + "message": "A: Vous pouvez me contacter via https://chrome.google.com/webstore/support/bkdpdcgcbkkohcelcibdenakcngkmamg#question de savoir si vous avez besoin de plus d'aide, et je vais essayer de répondre en temps opportun.", + "description": "Comment contacter pour plus d'aide" + } +} diff --git a/add.html b/add.html new file mode 100644 index 0000000..dcc1d33 --- /dev/null +++ b/add.html @@ -0,0 +1,19 @@ + + + + + + +

+
+ + +
+
+ + +
+ + + + diff --git a/add.js b/add.js new file mode 100644 index 0000000..321a34f --- /dev/null +++ b/add.js @@ -0,0 +1,174 @@ +/******************************************************************************* + * Declare variables + ******************************************************************************/ +var details; //Stores the details sent from the content script + +/******************************************************************************* + * Functions + ******************************************************************************/ + +function showInfo(url) { +//Displays web clip info in popup + document.getElementById('icon').src = url; + document.getElementById('add').disabled = ''; +} + +function randomId() { +//Generates a random hex id in Chrome's app id format + var str = ''; + for (var i = 0; i < 32; i++) { + str += String.fromCharCode(Math.floor(Math.random() * 16) + 97); + } + return str; +} + +function dataURItoBlob(dataURI) { +//Convert base64 to raw binary data held in a string + //(doesn't handle URLEncoded DataURIs) + var byteString = atob(dataURI.split(',')[1]); + //Separate out the mime component + var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] + //Write the bytes of the string to an array + var array = []; + for (var i = 0; i < byteString.length; i++) { + array.push(byteString.charCodeAt(i)); + } + //Write the array to a blob and return + return new Blob([new Uint8Array(array)], {type: mimeString}); +} + +function errorHandler(e) { + var msg = ''; + switch (e.code) { + case FileError.QUOTA_EXCEEDED_ERR: + msg = 'QUOTA_EXCEEDED_ERR'; + break; + case FileError.NOT_FOUND_ERR: + msg = 'NOT_FOUND_ERR'; + break; + case FileError.SECURITY_ERR: + msg = 'SECURITY_ERR'; + break; + case FileError.INVALID_MODIFICATION_ERR: + msg = 'INVALID_MODIFICATION_ERR'; + break; + case FileError.INVALID_STATE_ERR: + msg = 'INVALID_STATE_ERR'; + break; + default: + msg = 'Unknown Error'; + break; + }; + console.error(msg); +} + +/******************************************************************************* + * Event listeners + ******************************************************************************/ + +//Listen for the content script trying to communicate +chrome.extension.onMessage.addListener(function(msg) { + if (msg.to == 'add.js' && msg.from == 'icon_finder.js') { //It's for us + details = msg.message; //Save the details for later, too + if (details.url) { //If it's the complete info, not just the title + details.id = randomId(); + if (details.icon == 'screenshot') { //If no icons are found, take a screenshot + console.log('Taking screenshot...'); + chrome.tabs.captureVisibleTab({'quality': 100}, function(dataUrl) { + //Shrink the screenshot & convert it to a blob + var canvas = document.createElement('canvas'); //Will use to apply effects + canvas.style.display = 'none'; //We don't want it to be visible, of course + document.body.appendChild(canvas); + var context = canvas.getContext('2d'); + var img = new Image(); + img.onload = function() { + var width = 128, height = 128; + if (this.width > this.height) { //If the screenshot is landscape + height = 128*this.height/this.width; + } else { //If the screenshot is portrait + width = 128*this.width/this.height; + } + canvas.width = 128; //Make the canvas icon-sized + canvas.height = 128; + //Draw the image data centered in the canvas + context.drawImage(this, (128-width)/2, (128-height)/2, width, height); + details.icon = canvas.toDataURL(); + document.body.removeChild(canvas); //Dispose of the canvas - we're done + showInfo(details.icon); + }; + img.src = dataUrl; //Load the screenshot into the image for processing + }); + } else { + showInfo(details.icon); + } + } else { //Nope, just the title was sent + document.getElementById('title').disabled = ''; + document.getElementById('title').value = details.title; + document.getElementById('title').select(); + } + } +}); + +document.getElementById('add').addEventListener('click', function() { + details.title = document.getElementById('title').value; + if (document.getElementById('icon').src.substring(0, 22) == + 'data:image/png;base64,') { //The icon is a screenshot + //Convert icon to blob + var imgBlob = dataURItoBlob(document.getElementById('icon').src); + //Webkit support for requestFileSystem + window.requestFileSystem = window.requestFileSystem || + window.webkitRequestFileSystem; + window.requestFileSystem(PERSISTENT, 1024*1024, function(fs) { + fs.root.getDirectory('icons', {create: true}, function(dirEntry) { + var name = details.id + '.png'; + dirEntry.getFile(name, {create: true}, function(fileEntry) { + fileEntry.createWriter(function(fileWriter) { + fileWriter.onwriteend = function(e) { + details.icon = fileEntry.toURL(); //Get the screenshot URL + chrome.extension.sendMessage({ //and send it to the + to: 'launcher.js', //background page + from: 'add.js', + message: details + }, window.close); + }; + fileWriter.onerror = function(e) { + console.log('Write failed: ' + e.toString()); + }; + fileWriter.write(imgBlob); //Write the screenshot to a file + }, errorHandler); + }, errorHandler); + }, errorHandler); + }, errorHandler); + } else { //The icon is a file + chrome.extension.sendMessage({ //Tell the background script about the icon + to: 'launcher.js', + from: 'add.js', + message: details + }, window.close); + } + //window.close(); +}, false); + +document.getElementById('title').addEventListener('keypress', function(event) { + if (event.keyCode == 13) { //They pressed Enter + document.getElementById('add').click(); + } +}, false); + +document.getElementById('title').addEventListener('input', function() { + if (document.getElementById('title').value == '') { + document.getElementById('add').disabled = 'disabled'; + } else { + document.getElementById('add').disabled = ''; + } +}, false); + +document.getElementById('cancel').addEventListener('click', function() { + window.close(); +}, false); + +/******************************************************************************* + * Post scripts + ******************************************************************************/ + +chrome.tabs.executeScript(null, {file: 'icon_finder.js'}); //Inject the content script diff --git a/chrome-webstore-item.html b/chrome-webstore-item.html new file mode 100755 index 0000000..2730b26 --- /dev/null +++ b/chrome-webstore-item.html @@ -0,0 +1,15 @@ + + + + + Chrome Web Store + + + + + This website has an app in the Chrome Web Store. + + + + + diff --git a/chrome-webstore-item.js b/chrome-webstore-item.js new file mode 100755 index 0000000..2a0c553 --- /dev/null +++ b/chrome-webstore-item.js @@ -0,0 +1,57 @@ +var hash = unescape(location.hash).split('&'); +var url = hash[0].substring(1); +var host = hash[1]; +var id = ''; +var extensionInfo; + +document.getElementById('host').innerText = host; + +document.getElementById('view').addEventListener('click', function() { + if (document.getElementById('view').innerText == 'View') { + window.open(url); + } else if (extensionInfo.isApp) { + chrome.management.launchApp(id); + } +}, false); + +document.addEventListener('contextmenu', function(event) { + event.preventDefault(); +}, false); + +window.onbeforeunload = function() { + //FIXME: Doesn't prevent the infobar from displaying next time. + //localStorage doesn't get set like it is supposed to + localStorage['infobar.hide.' + url] = 'true'; + console.log('infobar.hide.' + url, localStorage['infobar.hide.' + url]); +} + +chrome.management.onInstalled.addListener(function(extensionInfo) { + alert(extensionInfo.id); + if (extensionInfo.id == id) { + //They installed the app, so switch to an Open button + document.getElementById('view').innerText = 'Open'; + document.getElementById('description').innerText = + extensionInfo.name + ' is installed.'; + if (!extensionInfo.isApp) { + document.getElementById('view').disabled = 'disabled'; + } + } +}); +//Double check that it really is the Chrome Web Store +if (url.substring(0, 34) == 'https://chrome.google.com/webstore') { + //Extract the extension ID from the URL + id = url.substr(url.lastIndexOf('/') + 1, 32); + //Check if app is installed + chrome.management.get(id, function(extInfo) { + if (extInfo) { + //It's installed, switch to an Open button + document.getElementById('view').innerText = 'Open'; + document.getElementById('description').innerText = + extInfo.name + ' is installed.'; + extensionInfo = extInfo; + if (!extInfo.isApp) { + document.getElementById('view').disabled = 'disabled'; + } + } + }); +} diff --git a/chrome-webstore-item_finder.js b/chrome-webstore-item_finder.js new file mode 100755 index 0000000..6f4b279 --- /dev/null +++ b/chrome-webstore-item_finder.js @@ -0,0 +1,16 @@ +//Looks for to suggest an app to the user + +var links = document.getElementsByTagName('link'); + +for (var i = 0; i < links.length; i++) { + if (links[i].rel == 'chrome-webstore-item') { + chrome.extension.sendMessage({ //Tell the background script to show the infobar + from: 'chrome-webstore-item_finder.js', + to: 'launcher.js', + message: { + 'url': links[i].href, + 'host': window.location.host + } + }); + } +} diff --git a/color-thief/.gitignore b/color-thief/.gitignore new file mode 100755 index 0000000..5fe4ed6 --- /dev/null +++ b/color-thief/.gitignore @@ -0,0 +1,41 @@ +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store* +ehthumbs.db +Icon? +Thumbs.db + +# App Files # +############# +*.tmproj +.sass-cache/* +Rakefile +rsync-exclude \ No newline at end of file diff --git a/color-thief/README.markdown b/color-thief/README.markdown new file mode 100755 index 0000000..38bccc9 --- /dev/null +++ b/color-thief/README.markdown @@ -0,0 +1,41 @@ +#Color Thief + +A script for grabbing the dominant color or color palette from an image. Uses javascript and canvas. + +[See a Demo](http://lokeshdhakar.com/projects/color-thief) | [Read more on my blog](http://lokeshdhakar.com/color-thief) + +##Usage + +###Get Dominant Color +```js +getDominantColor(sourceImage) +``` + +```js +returns [num, num, num] +``` + +Uses the median cut algorithm provided by quantize.js to cluster similar +colors and return the base color from the largest cluster. + +###Create Palette +```js +createPalette(sourceImage, colorCount) +``` + +```js +returns [ [num, num, num], [num, num, num], ... ] +``` + +Use the median cut algorithm provided by quantize.js to cluster similar +colors. + +##License +by Lokesh Dhakar | [lokeshdhakar.com](http://www.lokeshdhakar.com) | [twitter.com/lokeshdhakar](http://twitter.com/lokeshdhakar) + +Thanks to [jfsiii](https://github.com/jfsiii) for a large number of code improvements and others for submitting issues and fixes. + +Licensed under the [Creative Commons Attribution 2.5 License](http://creativecommons.org/licenses/by/2.5/) + +* Free for use in both personal and commercial projects. +* Attribution requires leaving author name, author homepage link, and the license info intact. \ No newline at end of file diff --git a/color-thief/css/app.css b/color-thief/css/app.css new file mode 100755 index 0000000..0b6b76d --- /dev/null +++ b/color-thief/css/app.css @@ -0,0 +1,451 @@ +/* line 17, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +/* line 20, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +body { + line-height: 1; +} + +/* line 22, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +ol, ul { + list-style: none; +} + +/* line 24, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +table { + border-collapse: collapse; + border-spacing: 0; +} + +/* line 26, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +caption, th, td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} + +/* line 28, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +q, blockquote { + quotes: none; +} +/* line 101, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +q:before, q:after, blockquote:before, blockquote:after { + content: ""; + content: none; +} + +/* line 30, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +a img { + border: none; +} + +/* line 114, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */ +article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary { + display: block; +} + +/* line 5, ../sass/app.sass */ +body, input, textarea { + margin: 40px; + color: #888888; + background: #222222; + font: 16px/1.625em "Varela Round", "lucida grande", tahoma, sans-serif; + -wbkite-font-smoothing: antialiased; +} + +/* line 12, ../sass/app.sass */ +h1, h2, h3, h4, h5, h6 { + color: white; + font-family: "Terminal Dosis", "lucida grande", tahoma, sans-serif; + line-height: 1em; + font-weight: 600; + margin-bottom: 0.5em; +} + +/* line 19, ../sass/app.sass */ +h1 { + font-size: 72px; + line-height: 0.5em; + margin-bottom: 0.3em; +} +/* line 23, ../sass/app.sass */ +h1 small { + font-size: 20px; +} +/* line 25, ../sass/app.sass */ +h1 span { + -webkit-transition: color 1s; + -moz-transition: color 1s; + -ms-transition: color 1s; + -o-transition: color 1s; + transition: color 1s; +} +/* line 28, ../sass/app.sass */ +h1:hover .char1 { + -webkit-transition: color 0.2s; + -moz-transition: color 0.2s; + -ms-transition: color 0.2s; + -o-transition: color 0.2s; + transition: color 0.2s; + color: red; +} +/* line 31, ../sass/app.sass */ +h1:hover .char2 { + -webkit-transition: color 0.2s 0.1s; + -moz-transition: color 0.2s 0.1s; + -ms-transition: color 0.2s 0.1s; + -o-transition: color 0.2s 0.1s; + transition: color 0.2s 0.1s; + color: orange; +} +/* line 34, ../sass/app.sass */ +h1:hover .char3 { + -webkit-transition: color 0.2s 0.2s; + -moz-transition: color 0.2s 0.2s; + -ms-transition: color 0.2s 0.2s; + -o-transition: color 0.2s 0.2s; + transition: color 0.2s 0.2s; + color: yellow; +} +/* line 37, ../sass/app.sass */ +h1:hover .char4 { + -webkit-transition: color 0.2s 0.3s; + -moz-transition: color 0.2s 0.3s; + -ms-transition: color 0.2s 0.3s; + -o-transition: color 0.2s 0.3s; + transition: color 0.2s 0.3s; + color: green; +} +/* line 40, ../sass/app.sass */ +h1:hover .char5 { + -webkit-transition: color 0.2s 0.4s; + -moz-transition: color 0.2s 0.4s; + -ms-transition: color 0.2s 0.4s; + -o-transition: color 0.2s 0.4s; + transition: color 0.2s 0.4s; + color: blue; +} +/* line 43, ../sass/app.sass */ +h1:hover .char6 { + -webkit-transition: color 0.2s 0.5s; + -moz-transition: color 0.2s 0.5s; + -ms-transition: color 0.2s 0.5s; + -o-transition: color 0.2s 0.5s; + transition: color 0.2s 0.5s; + color: indigo; +} +/* line 46, ../sass/app.sass */ +h1:hover .char7 { + -webkit-transition: color 0.2s 0.6s; + -moz-transition: color 0.2s 0.6s; + -ms-transition: color 0.2s 0.6s; + -o-transition: color 0.2s 0.6s; + transition: color 0.2s 0.6s; + color: violet; +} +/* line 49, ../sass/app.sass */ +h1:hover .char8 { + -webkit-transition: color 0.2s 0.7s; + -moz-transition: color 0.2s 0.7s; + -ms-transition: color 0.2s 0.7s; + -o-transition: color 0.2s 0.7s; + transition: color 0.2s 0.7s; + color: red; +} +/* line 52, ../sass/app.sass */ +h1:hover .char9 { + -webkit-transition: color 0.2s 0.8s; + -moz-transition: color 0.2s 0.8s; + -ms-transition: color 0.2s 0.8s; + -o-transition: color 0.2s 0.8s; + transition: color 0.2s 0.8s; + color: orange; +} +/* line 55, ../sass/app.sass */ +h1:hover .char10 { + -webkit-transition: color 0.2s 0.9s; + -moz-transition: color 0.2s 0.9s; + -ms-transition: color 0.2s 0.9s; + -o-transition: color 0.2s 0.9s; + transition: color 0.2s 0.9s; + color: yellow; +} +/* line 58, ../sass/app.sass */ +h1:hover .char11 { + -webkit-transition: color 0.2s 1s; + -moz-transition: color 0.2s 1s; + -ms-transition: color 0.2s 1s; + -o-transition: color 0.2s 1s; + transition: color 0.2s 1s; + color: green; +} + +/* line 62, ../sass/app.sass */ +h2 { + font-size: 40px; + line-height: 1.2em; + text-align: center; +} + +/* line 67, ../sass/app.sass */ +h3 { + font-size: 16px; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +/* line 72, ../sass/app.sass */ +h4 { + font-size: 20px; + margin-bottom: 1.25em; +} + +/* line 76, ../sass/app.sass */ +p { + margin-bottom: 1.25em; +} + +/* line 80, ../sass/app.sass */ +strong { + font-weight: bold; +} + +/* Forms */ +/* line 86, ../sass/app.sass */ +input[type=text], input[type=password] { + background: #fafafa; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + border: 1px solid #dddddd; + color: #888888; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -ms-border-radius: 4px; + -o-border-radius: 4px; + border-radius: 4px; +} + +/* line 93, ../sass/app.sass */ +textarea { + background: #fafafa; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1); + border: 1px solid #dddddd; + color: #888888; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -ms-border-radius: 4px; + -o-border-radius: 4px; + border-radius: 4px; +} + +/* line 100, ../sass/app.sass */ +input[type=text]:focus { + color: #373737; +} + +/* line 103, ../sass/app.sass */ +textarea { + padding-left: 3px; + width: 98%; +} +/* line 104, ../sass/app.sass */ +textarea:focus { + color: #373737; +} + +/* line 109, ../sass/app.sass */ +input[type=text] { + padding: 3px; +} + +/* Links */ +/* line 114, ../sass/app.sass */ +a { + color: #09a1ec; + text-decoration: none; +} +/* line 117, ../sass/app.sass */ +a:hover { + color: #7fd2fa; +} + +/* line 120, ../sass/app.sass */ +#container { + width: 900px; + margin: 0 auto; +} + +/* line 124, ../sass/app.sass */ +header { + padding-bottom: 40px; + text-align: center; + width: 600px; + margin: 0 auto; +} + +/* line 130, ../sass/app.sass */ +.medianCutPalette h3 { + margin-top: 20px; +} + +/* line 133, ../sass/app.sass */ +.imageSection { + margin-bottom: 80px; + background: #111111; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + -ms-border-radius: 10px; + -o-border-radius: 10px; + border-radius: 10px; + *zoom: 1; +} +/* line 38, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.imageSection:after { + content: ""; + display: table; + clear: both; +} +/* line 138, ../sass/app.sass */ +.imageSection .imageWrap { + -moz-border-radius-topleft: 10px; + -webkit-border-top-left-radius: 10px; + -ms-border-top-left-radius: 10px; + -o-border-top-left-radius: 10px; + border-top-left-radius: 10px; + -moz-border-radius-bottomleft: 10px; + -webkit-border-bottom-left-radius: 10px; + -ms-border-bottom-left-radius: 10px; + -o-border-bottom-left-radius: 10px; + border-bottom-left-radius: 10px; + width: 400px; + height: 300px; + float: left; + margin-right: 20px; + background: url(../img/dark_checkered_bg.png); +} +/* line 145, ../sass/app.sass */ +.imageSection .imageWrap .targetImage { + -moz-border-radius-topleft: 10px; + -webkit-border-top-left-radius: 10px; + -ms-border-top-left-radius: 10px; + -o-border-top-left-radius: 10px; + border-top-left-radius: 10px; + -moz-border-radius-bottomleft: 10px; + -webkit-border-bottom-left-radius: 10px; + -ms-border-bottom-left-radius: 10px; + -o-border-bottom-left-radius: 10px; + border-bottom-left-radius: 10px; +} +/* line 147, ../sass/app.sass */ +.imageSection .colors { + margin-top: 20px; + width: 400px; + float: left; +} +/* line 151, ../sass/app.sass */ +.imageSection .colors .function { + clear: left; + margin-bottom: 10px; + *zoom: 1; +} +/* line 38, ../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.imageSection .colors .function:after { + content: ""; + display: table; + clear: both; +} +/* line 155, ../sass/app.sass */ +.imageSection .colors .function .swatches .swatch { + width: 40px; + height: 20px; + margin-right: 2px; + background: #dddddd; + float: left; + -webkit-transition: all 0.5s; + -moz-transition: all 0.5s; + -ms-transition: all 0.5s; + -o-transition: all 0.5s; + transition: all 0.5s; +} +/* line 162, ../sass/app.sass */ +.imageSection .colors .function .swatches .swatch:hover { + -webkit-transition: none; + -moz-transition: none; + -ms-transition: none; + -o-transition: none; + transition: none; + -webkit-transform: scale(1.2, 1.2); + -moz-transform: scale(1.2, 1.2); + -ms-transform: scale(1.2, 1.2); + -o-transform: scale(1.2, 1.2); + transform: scale(1.2, 1.2); + -webkit-box-shadow: 0 1px 10px black; + -moz-box-shadow: 0 1px 10px black; + box-shadow: 0 1px 10px black; +} +/* line 166, ../sass/app.sass */ +.imageSection .colors .function .swatches .swatch:first-child { + -moz-border-radius-topleft: 4px; + -webkit-border-top-left-radius: 4px; + -ms-border-top-left-radius: 4px; + -o-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -webkit-border-bottom-left-radius: 4px; + -ms-border-bottom-left-radius: 4px; + -o-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; +} +/* line 168, ../sass/app.sass */ +.imageSection .colors .function .swatches .swatch:last-child { + -moz-border-radius-topright: 4px; + -webkit-border-top-right-radius: 4px; + -ms-border-top-right-radius: 4px; + -o-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + -ms-border-bottom-right-radius: 4px; + -o-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +/* Hardcoding the offset for the FB icon example */ +/* line 172, ../sass/app.sass */ +.fbIcon .imageWrap .targetImage { + -webkit-border-radius: 0; + -moz-border-radius: 0; + -ms-border-radius: 0; + -o-border-radius: 0; + border-radius: 0; + position: relative; + top: 142px; + left: 192px; +} + +/* line 178, ../sass/app.sass */ +canvas { + display: none; +} diff --git a/color-thief/img/3.jpg b/color-thief/img/3.jpg new file mode 100755 index 0000000..a7b2763 Binary files /dev/null and b/color-thief/img/3.jpg differ diff --git a/color-thief/img/4.jpg b/color-thief/img/4.jpg new file mode 100755 index 0000000..aacb760 Binary files /dev/null and b/color-thief/img/4.jpg differ diff --git a/color-thief/img/5.jpg b/color-thief/img/5.jpg new file mode 100755 index 0000000..a9e0bc3 Binary files /dev/null and b/color-thief/img/5.jpg differ diff --git a/color-thief/img/dark_checkered_bg.png b/color-thief/img/dark_checkered_bg.png new file mode 100755 index 0000000..10f2199 Binary files /dev/null and b/color-thief/img/dark_checkered_bg.png differ diff --git a/color-thief/img/icon1.png b/color-thief/img/icon1.png new file mode 100755 index 0000000..3ef7927 Binary files /dev/null and b/color-thief/img/icon1.png differ diff --git a/color-thief/img/logo1.png b/color-thief/img/logo1.png new file mode 100755 index 0000000..11daa76 Binary files /dev/null and b/color-thief/img/logo1.png differ diff --git a/color-thief/index.html b/color-thief/index.html new file mode 100755 index 0000000..bc053b1 --- /dev/null +++ b/color-thief/index.html @@ -0,0 +1,69 @@ + + + + + + + + + Color Thief + + + + + + + + + + + +
+
+

Color Thief

+

by Lokesh Dhakar

+ +

A script for grabbing the dominant color or color palette from an image. Uses Javascript and the canvas tag to make it happen.

+

Read more on my blog | Get the code on Github +

+
+ +

Examples

+
+ +
+
+ + + + + + + + + + + + + + + + diff --git a/color-thief/index.js b/color-thief/index.js new file mode 100755 index 0000000..014c6d7 --- /dev/null +++ b/color-thief/index.js @@ -0,0 +1,45 @@ +$(document).ready(function () { + + // Use mustache.js templating to create layout + + var imageArray = { images: [ + {"file": "3.jpg"}, + {"file": "4.jpg"}, + {"file": "5.jpg"}, + {"file": "logo1.png"}, + {"file": "icon1.png", "colorCount": "4", "class": "fbIcon"} + ]}; + + var html = Mustache.to_html($('#template').html(), imageArray); + $('#main').append(html); + + // Use lettering.js to give letter by letter styling control for the h1 title + $("h1").lettering(); + + + // For each image: + // Once image is loaded, get dominant color and palette and display them. + $('img').bind('load', function (event) { + var image = event.target; + var $image = $(image); + var imageSection = $image.closest('.imageSection'); + var appendColors = function (colors, root) { + $.each(colors, function (index, value) { + var swatchEl = $('
', {'class': 'swatch'}) + .css('background-color', 'rgba('+ value +', 1)'); + root.append(swatchEl); + }); + }; + + // Dominant Color + var dominantColor = getDominantColor(image); + var dominantSwatch = imageSection.find('.dominantColor .swatches'); + appendColors([dominantColor], dominantSwatch); + + // Palette + var colorCount = $image.attr('data-colorcount') ? $image.data('colorcount') : 10; + var medianPalette = createPalette(image, colorCount); + var medianCutPalette = imageSection.find('.medianCutPalette .swatches'); + appendColors(medianPalette, medianCutPalette); + }); +}); \ No newline at end of file diff --git a/color-thief/js/color-thief.js b/color-thief/js/color-thief.js new file mode 100755 index 0000000..a4b647a --- /dev/null +++ b/color-thief/js/color-thief.js @@ -0,0 +1,228 @@ +/* + * Color Thief v1.0 + * by Lokesh Dhakar - http://www.lokeshdhakar.com + * + * Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ + * + * # Thanks + * Nick Rabinowitz: Created quantize.js which is used by the median cut palette function. This handles all the hard clustering math. + * John Schulz: All around mad genius who helped clean and optimize the code. @JFSIII + * + * ## Classes + * CanvasImage + * ## Functions + * getDominantColor() + * createPalette() + * getAverageRGB() + * createAreaBasedPalette() + * + * Requires jquery and quantize.js. + */ + + +/* + CanvasImage Class + Class that wraps the html image element and canvas. + It also simplifies some of the canvas context manipulation + with a set of helper functions. +*/ +var CanvasImage = function (image) { + // If jquery object is passed in, get html element + imgEl = (image.jquery) ? image[0] : image; + + this.canvas = document.createElement('canvas'); + this.context = this.canvas.getContext('2d'); + + document.body.appendChild(this.canvas); + + this.width = this.canvas.width = imgEl.width; + this.height = this.canvas.height = imgEl.height; + + this.context.drawImage(imgEl, 0, 0, this.width, this.height); +}; + +CanvasImage.prototype.clear = function () { + this.context.clearRect(0, 0, this.width, this.height); +}; + +CanvasImage.prototype.update = function (imageData) { + this.context.putImageData(imageData, 0, 0); +}; + +CanvasImage.prototype.getPixelCount = function () { + return this.width * this.height; +}; + +CanvasImage.prototype.getImageData = function () { + return this.context.getImageData(0, 0, this.width, this.height); +}; + +CanvasImage.prototype.removeCanvas = function () { + $(this.canvas).remove(); +}; + + +/* + * getDominantColor(sourceImage) + * returns {r: num, g: num, b: num} + * + * Use the median cut algorithm provided by quantize.js to cluster similar + * colors and return the base color from the largest cluster. */ +function getDominantColor(sourceImage) { + + var palette = createPalette(sourceImage, 5); + var dominant = palette[0]; + + return dominant; +} + + +/* + * createPalette(sourceImage, colorCount) + * returns array[ {r: num, g: num, b: num}, {r: num, g: num, b: num}, ...] + * + * Use the median cut algorithm provided by quantize.js to cluster similar + * colors. + * + * BUGGY: Function does not always return the requested amount of colors. It can be +/- 2. + */ +function createPalette(sourceImage, colorCount) { + + // Create custom CanvasImage object + var image = new CanvasImage(sourceImage), + imageData = image.getImageData(), + pixels = imageData.data, + pixelCount = image.getPixelCount(); + + // Store the RGB values in an array format suitable for quantize function + var pixelArray = []; + for (var i = 0, offset, r, g, b, a; i < pixelCount; i++) { + offset = i * 4; + r = pixels[offset + 0]; + g = pixels[offset + 1]; + b = pixels[offset + 2]; + a = pixels[offset + 3]; + // If pixel is mostly opaque and not white + if (a >= 125) { + if (!(r > 250 && g > 250 && b > 250)) { + pixelArray.push([r, g, b]); + } + } + } + + // Send array to quantize function which clusters values + // using median cut algorithm + + var cmap = MMCQ.quantize(pixelArray, colorCount); + var palette = cmap.palette(); + + // Clean up + image.removeCanvas(); + + return palette; + +} + + +/* + * getAverageRGB(sourceImage) + * returns {r: num, g: num, b: num} + * + * Add up all pixels RGB values and return average. + * Tends to return muddy gray/brown color. Most likely, you'll be better + * off using getDominantColor() instead. + */ +function getAverageRGB(sourceImage) { + // Config + var sampleSize = 10; + + // Create custom CanvasImage object + var image = new CanvasImage(sourceImage), + imageData = image.getImageData(), + pixels = imageData.data, + pixelCount = image.getPixelCount(); + + // Reset vars + var i = 0, + count = 0, + rgb = {r:0, g:0, b:0}; + + // Loop through every # pixels. (# is set in Config above via the blockSize var) + // Add all the red values together, repeat for blue and green. + // Last step, divide by the number of pixels checked to get average. + while ( (i += sampleSize * 4) < pixelCount ) { + // if pixel is mostly opaque + if (pixels[i+3] > 125) { + ++count; + rgb.r += pixels[i]; + rgb.g += pixels[i+1]; + rgb.b += pixels[i+2]; + } + } + + rgb.r = ~~(rgb.r/count); + rgb.g = ~~(rgb.g/count); + rgb.b = ~~(rgb.b/count); + + return rgb; +} + + +/* + * createAreaBasedPalette(sourceImage, colorCount) + * returns array[ {r: num, g: num, b: num}, {r: num, g: num, b: num}, ...] + * + * Break the image into sections. Loops through pixel RGBS in the section and average color. + * Tends to return muddy gray/brown color. You're most likely better off using createPalette(). + * + * BUGGY: Function does not always return the requested amount of colors. It can be +/- 2. + * + */ +function createAreaBasedPalette(sourceImage, colorCount) { + + var palette = []; + + // Create custom CanvasImage object + var image = new CanvasImage(sourceImage), + imageData = image.getImageData(), + pixels = imageData.data, + pixelCount = image.getPixelCount(); + + + // How big a pixel area does each palette color get + var rowCount = Math.round(Math.sqrt(colorCount)), + colCount = rowCount, + colWidth = Math.round(image.width / colCount), + rowHeight = Math.round(image.height / rowCount); + + // Loop through pixels section by section. + // At the end of each section, push the average rgb color to palette array. + for (var i = 0, vertOffset; i").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i. +shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j +)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/color-thief/js/libs/jquery.lettering.js b/color-thief/js/libs/jquery.lettering.js new file mode 100755 index 0000000..4515590 --- /dev/null +++ b/color-thief/js/libs/jquery.lettering.js @@ -0,0 +1,66 @@ +/*global jQuery */ +/*! +* Lettering.JS 0.6.1 +* +* Copyright 2010, Dave Rupert http://daverupert.com +* Released under the WTFPL license +* http://sam.zoy.org/wtfpl/ +* +* Thanks to Paul Irish - http://paulirish.com - for the feedback. +* +* Date: Mon Sep 20 17:14:00 2010 -0600 +*/ +(function($){ + function injector(t, splitter, klass, after) { + var a = t.text().split(splitter), inject = ''; + if (a.length) { + $(a).each(function(i, item) { + inject += ''+item+''+after; + }); + t.empty().append(inject); + } + } + + var methods = { + init : function() { + + return this.each(function() { + injector($(this), '', 'char', ''); + }); + + }, + + words : function() { + + return this.each(function() { + injector($(this), ' ', 'word', ' '); + }); + + }, + + lines : function() { + + return this.each(function() { + var r = "eefec303079ad17405c889e092e105b0"; + // Because it's hard to split a
tag consistently across browsers, + // (*ahem* IE *ahem*), we replaces all
instances with an md5 hash + // (of the word "split"). If you're trying to use this plugin on that + // md5 hash string, it will fail because you're being ridiculous. + injector($(this).children("br").replaceWith(r).end(), r, 'line', ''); + }); + + } + }; + + $.fn.lettering = function( method ) { + // Method calling logic + if ( method && methods[method] ) { + return methods[ method ].apply( this, [].slice.call( arguments, 1 )); + } else if ( method === 'letters' || ! method ) { + return methods.init.apply( this, [].slice.call( arguments, 0 ) ); // always pass an array + } + $.error( 'Method ' + method + ' does not exist on jQuery.lettering' ); + return this; + }; + +})(jQuery); \ No newline at end of file diff --git a/color-thief/js/libs/modernizr-2.0.6.min.js b/color-thief/js/libs/modernizr-2.0.6.min.js new file mode 100755 index 0000000..b8d5154 --- /dev/null +++ b/color-thief/js/libs/modernizr-2.0.6.min.js @@ -0,0 +1,4 @@ +/* Modernizr 2.0.6 | MIT & BSD + * Contains: All core tests, html5shiv, yepnope, respond.js. Get your own custom build at www.modernizr.com/download/ + */ +;window.Modernizr=function(a,b,c){function I(){e.input=function(a){for(var b=0,c=a.length;b",a,""].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(b){if(a.matchMedia)return matchMedia(b).matches;var c;v("@media "+b+" { #"+i+" { position: absolute; } }",function(b){c=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position=="absolute"});return c},x=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=D(e[d],"function"),D(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),y,z={}.hasOwnProperty,A;!D(z,c)&&!D(z.call,c)?A=function(a,b){return z.call(a,b)}:A=function(a,b){return b in a&&D(a.constructor.prototype[b],c)};var H=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!D(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return x("dragstart")&&x("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b";return(a.firstChild&&a.firstChild.namespaceURI)==q.svg},r.smil=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"animate")))},r.svgclippaths=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"clipPath")))};for(var J in r)A(r,J)&&(y=J.toLowerCase(),e[y]=r[J](),u.push((e[y]?"":"no-")+y));e.input||I(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)A(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return;b=typeof b=="boolean"?b:!!b(),g.className+=" "+(b?"":"no-")+a,e[a]=b}return e},B(""),j=l=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b=u.minw)&&(!u.maxw||u.maxw&&l<=u.maxw))m[u.media]||(m[u.media]=[]),m[u.media].push(f[u.rules])}for(var t in g)g[t]&&g[t].parentNode===j&&j.removeChild(g[t]);for(var t in m){var v=c.createElement("style"),w=m[t].join("\n");v.type="text/css",v.media=t,v.styleSheet?v.styleSheet.cssText=w:v.appendChild(c.createTextNode(w)),n.appendChild(v),g.push(v)}j.insertBefore(n,o.nextSibling)}},s=function(a,b){var c=t();if(!!c){c.open("GET",a,!0),c.onreadystatechange=function(){c.readyState==4&&(c.status==200||c.status==304)&&b(c.responseText)};if(c.readyState==4)return;c.send()}},t=function(){var a=!1,b=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new XMLHttpRequest}],c=b.length;while(c--){try{a=b[c]()}catch(d){continue}break}return function(){return a}}();m(),respond.update=m,a.addEventListener?a.addEventListener("resize",u,!1):a.attachEvent&&a.attachEvent("onresize",u)}}(this,Modernizr.mq("only all")),function(a,b,c){function k(a){return!a||a=="loaded"||a=="complete"}function j(){var a=1,b=-1;while(p.length- ++b)if(p[b].s&&!(a=p[b].r))break;a&&g()}function i(a){var c=b.createElement("script"),d;c.src=a.s,c.onreadystatechange=c.onload=function(){!d&&k(c.readyState)&&(d=1,j(),c.onload=c.onreadystatechange=null)},m(function(){d||(d=1,j())},H.errorTimeout),a.e?c.onload():n.parentNode.insertBefore(c,n)}function h(a){var c=b.createElement("link"),d;c.href=a.s,c.rel="stylesheet",c.type="text/css";if(!a.e&&(w||r)){var e=function(a){m(function(){if(!d)try{a.sheet.cssRules.length?(d=1,j()):e(a)}catch(b){b.code==1e3||b.message=="security"||b.message=="denied"?(d=1,m(function(){j()},0)):e(a)}},0)};e(c)}else c.onload=function(){d||(d=1,m(function(){j()},0))},a.e&&c.onload();m(function(){d||(d=1,j())},H.errorTimeout),!a.e&&n.parentNode.insertBefore(c,n)}function g(){var a=p.shift();q=1,a?a.t?m(function(){a.t=="c"?h(a):i(a)},0):(a(),j()):q=0}function f(a,c,d,e,f,h){function i(){!o&&k(l.readyState)&&(r.r=o=1,!q&&j(),l.onload=l.onreadystatechange=null,m(function(){u.removeChild(l)},0))}var l=b.createElement(a),o=0,r={t:d,s:c,e:h};l.src=l.data=c,!s&&(l.style.display="none"),l.width=l.height="0",a!="object"&&(l.type=d),l.onload=l.onreadystatechange=i,a=="img"?l.onerror=i:a=="script"&&(l.onerror=function(){r.e=r.r=1,g()}),p.splice(e,0,r),u.insertBefore(l,s?null:n),m(function(){o||(u.removeChild(l),r.r=r.e=o=1,j())},H.errorTimeout)}function e(a,b,c){var d=b=="c"?z:y;q=0,b=b||"j",C(a)?f(d,a,b,this.i++,l,c):(p.splice(this.i++,0,a),p.length==1&&g());return this}function d(){var a=H;a.loader={load:e,i:0};return a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=r&&!s,u=s?l:n.parentNode,v=a.opera&&o.call(a.opera)=="[object Opera]",w="webkitAppearance"in l.style,x=w&&"async"in b.createElement("script"),y=r?"object":v||x?"img":"script",z=w?"img":y,A=Array.isArray||function(a){return o.call(a)=="[object Array]"},B=function(a){return Object(a)===a},C=function(a){return typeof a=="string"},D=function(a){return o.call(a)=="[object Function]"},E=[],F={},G,H;H=function(a){function f(a){var b=a.split("!"),c=E.length,d=b.pop(),e=b.length,f={url:d,origUrl:d,prefixes:b},g,h;for(h=0;h|\\{|%)?([^\\/#\\^]+?)\\1?" + ctag + "+", "g"); + }); + }; + + var regex = new_regex(); + var tag_replace_callback = function(match, operator, name) { + switch(operator) { + case "!": // ignore comments + return ""; + case "=": // set new delimiters, rebuild the replace regexp + that.set_delimiters(name); + regex = new_regex(); + return ""; + case ">": // render partial + return that.render_partial(name, context, partials); + case "{": // the triple mustache is unescaped + return that.find(name, context); + default: // escape the value + return that.escape(that.find(name, context)); + } + }; + var lines = template.split("\n"); + for(var i = 0; i < lines.length; i++) { + lines[i] = lines[i].replace(regex, tag_replace_callback, this); + if(!in_recursion) { + this.send(lines[i]); + } + } + + if(in_recursion) { + return lines.join("\n"); + } + }, + + set_delimiters: function(delimiters) { + var dels = delimiters.split(" "); + this.otag = this.escape_regex(dels[0]); + this.ctag = this.escape_regex(dels[1]); + }, + + escape_regex: function(text) { + // thank you Simon Willison + if(!arguments.callee.sRE) { + var specials = [ + '/', '.', '*', '+', '?', '|', + '(', ')', '[', ']', '{', '}', '\\' + ]; + arguments.callee.sRE = new RegExp( + '(\\' + specials.join('|\\') + ')', 'g' + ); + } + return text.replace(arguments.callee.sRE, '\\$1'); + }, + + /* + find `name` in current `context`. That is find me a value + from the view object + */ + find: function(name, context) { + name = this.trim(name); + + // Checks whether a value is thruthy or false or 0 + function is_kinda_truthy(bool) { + return bool === false || bool === 0 || bool; + } + + var value; + + // check for dot notation eg. foo.bar + if(name.match(/([a-z_]+)\./ig)){ + value = is_kinda_truthy(this.walk_context(name, context)); + } + else{ + if(is_kinda_truthy(context[name])) { + value = context[name]; + } else if(is_kinda_truthy(this.context[name])) { + value = this.context[name]; + } + } + + if(typeof value === "function") { + return value.apply(context); + } + if(value !== undefined) { + return value; + } + // silently ignore unkown variables + return ""; + }, + + walk_context: function(name, context){ + var path = name.split('.'); + // if the var doesn't exist in current context, check the top level context + var value_context = (context[path[0]] != undefined) ? context : this.context; + var value = value_context[path.shift()]; + while(value != undefined && path.length > 0){ + value_context = value; + value = value[path.shift()]; + } + // if the value is a function, call it, binding the correct context + if(typeof value === "function") { + return value.apply(value_context); + } + return value; + }, + + // Utility methods + + /* includes tag */ + includes: function(needle, haystack) { + return haystack.indexOf(this.otag + needle) != -1; + }, + + /* + Does away with nasty characters + */ + escape: function(s) { + s = String(s === null ? "" : s); + return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) { + switch(s) { + case "&": return "&"; + case '"': return '"'; + case "'": return '''; + case "<": return "<"; + case ">": return ">"; + default: return s; + } + }); + }, + + // by @langalex, support for arrays of strings + create_context: function(_context) { + if(this.is_object(_context)) { + return _context; + } else { + var iterator = "."; + if(this.pragmas["IMPLICIT-ITERATOR"]) { + iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator; + } + var ctx = {}; + ctx[iterator] = _context; + return ctx; + } + }, + + is_object: function(a) { + return a && typeof a == "object"; + }, + + is_array: function(a) { + return Object.prototype.toString.call(a) === '[object Array]'; + }, + + /* + Gets rid of leading and trailing whitespace + */ + trim: function(s) { + return s.replace(/^\s*|\s*$/g, ""); + }, + + /* + Why, why, why? Because IE. Cry, cry cry. + */ + map: function(array, fn) { + if (typeof array.map == "function") { + return array.map(fn); + } else { + var r = []; + var l = array.length; + for(var i = 0; i < l; i++) { + r.push(fn(array[i])); + } + return r; + } + }, + + getCachedRegex: function(name, generator) { + var byOtag = regexCache[this.otag]; + if (!byOtag) { + byOtag = regexCache[this.otag] = {}; + } + + var byCtag = byOtag[this.ctag]; + if (!byCtag) { + byCtag = byOtag[this.ctag] = {}; + } + + var regex = byCtag[name]; + if (!regex) { + regex = byCtag[name] = generator(this.otag, this.ctag); + } + + return regex; + } + }; + + return({ + name: "mustache.js", + version: "0.4.0-dev", + + /* + Turns a template and view into HTML + */ + to_html: function(template, view, partials, send_fun) { + var renderer = new Renderer(); + if(send_fun) { + renderer.send = send_fun; + } + renderer.render(template, view || {}, partials); + if(!send_fun) { + return renderer.buffer.join("\n"); + } + } + }); +}(); diff --git a/color-thief/js/libs/quantize.js b/color-thief/js/libs/quantize.js new file mode 100755 index 0000000..deaae77 --- /dev/null +++ b/color-thief/js/libs/quantize.js @@ -0,0 +1,471 @@ +/*! + * quantize.js Copyright 2008 Nick Rabinowitz. + * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php + */ + +// fill out a couple protovis dependencies +/*! + * Block below copied from Protovis: http://mbostock.github.com/protovis/ + * Copyright 2010 Stanford Visualization Group + * Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php + */ +if (!pv) { + var pv = { + map: function(array, f) { + var o = {}; + return f + ? array.map(function(d, i) { o.index = i; return f.call(o, d); }) + : array.slice(); + }, + naturalOrder: function(a, b) { + return (a < b) ? -1 : ((a > b) ? 1 : 0); + }, + sum: function(array, f) { + var o = {}; + return array.reduce(f + ? function(p, d, i) { o.index = i; return p + f.call(o, d); } + : function(p, d) { return p + d; }, 0); + }, + max: function(array, f) { + return Math.max.apply(null, f ? pv.map(array, f) : array); + } + } +} + +/** + * Basic Javascript port of the MMCQ (modified median cut quantization) + * algorithm from the Leptonica library (http://www.leptonica.com/). + * Returns a color map you can use to map original pixels to the reduced + * palette. Still a work in progress. + * + * @author Nick Rabinowitz + * @example + +// array of pixels as [R,G,B] arrays +var myPixels = [[190,197,190], [202,204,200], [207,214,210], [211,214,211], [205,207,207] + // etc + ]; +var maxColors = 4; + +var cmap = MMCQ.quantize(myPixels, maxColors); +var newPalette = cmap.palette(); +var newPixels = myPixels.map(function(p) { + return cmap.map(p); +}); + + */ +var MMCQ = (function() { + // private constants + var sigbits = 5, + rshift = 8 - sigbits, + maxIterations = 1000, + fractByPopulations = 0.75; + + // get reduced-space color index for a pixel + function getColorIndex(r, g, b) { + return (r << (2 * sigbits)) + (g << sigbits) + b; + } + + // Simple priority queue + function PQueue(comparator) { + var contents = [], + sorted = false; + + function sort() { + contents.sort(comparator); + sorted = true; + } + + return { + push: function(o) { + contents.push(o); + sorted = false; + }, + peek: function(index) { + if (!sorted) sort(); + if (index===undefined) index = contents.length - 1; + return contents[index]; + }, + pop: function() { + if (!sorted) sort(); + return contents.pop(); + }, + size: function() { + return contents.length; + }, + map: function(f) { + return contents.map(f); + }, + debug: function() { + if (!sorted) sort(); + return contents; + } + }; + } + + // 3d color space box + function VBox(r1, r2, g1, g2, b1, b2, histo) { + var vbox = this; + vbox.r1 = r1; + vbox.r2 = r2; + vbox.g1 = g1; + vbox.g2 = g2; + vbox.b1 = b1; + vbox.b2 = b2; + vbox.histo = histo; + } + VBox.prototype = { + volume: function(force) { + var vbox = this; + if (!vbox._volume || force) { + vbox._volume = ((vbox.r2 - vbox.r1 + 1) * (vbox.g2 - vbox.g1 + 1) * (vbox.b2 - vbox.b1 + 1)); + } + return vbox._volume; + }, + count: function(force) { + var vbox = this, + histo = vbox.histo; + if (!vbox._count_set || force) { + var npix = 0, + i, j, k; + for (i = vbox.r1; i <= vbox.r2; i++) { + for (j = vbox.g1; j <= vbox.g2; j++) { + for (k = vbox.b1; k <= vbox.b2; k++) { + index = getColorIndex(i,j,k); + npix += (histo[index] || 0); + } + } + } + vbox._count = npix; + vbox._count_set = true; + } + return vbox._count; + }, + copy: function() { + var vbox = this; + return new VBox(vbox.r1, vbox.r2, vbox.g1, vbox.g2, vbox.b1, vbox.b2, vbox.histo); + }, + avg: function(force) { + var vbox = this, + histo = vbox.histo; + if (!vbox._avg || force) { + var ntot = 0, + mult = 1 << (8 - sigbits), + rsum = 0, + gsum = 0, + bsum = 0, + hval, + i, j, k, histoindex; + for (i = vbox.r1; i <= vbox.r2; i++) { + for (j = vbox.g1; j <= vbox.g2; j++) { + for (k = vbox.b1; k <= vbox.b2; k++) { + histoindex = getColorIndex(i,j,k); + hval = histo[histoindex] || 0; + ntot += hval; + rsum += (hval * (i + 0.5) * mult); + gsum += (hval * (j + 0.5) * mult); + bsum += (hval * (k + 0.5) * mult); + } + } + } + if (ntot) { + vbox._avg = [~~(rsum/ntot), ~~(gsum/ntot), ~~(bsum/ntot)]; + } else { +// console.log('empty box'); + vbox._avg = [ + ~~(mult * (vbox.r1 + vbox.r2 + 1) / 2), + ~~(mult * (vbox.g1 + vbox.g2 + 1) / 2), + ~~(mult * (vbox.b1 + vbox.b2 + 1) / 2) + ]; + } + } + return vbox._avg; + }, + contains: function(pixel) { + var vbox = this, + rval = pixel[0] >> rshift; + gval = pixel[1] >> rshift; + bval = pixel[2] >> rshift; + return (rval >= vbox.r1 && rval <= vbox.r2 && + gval >= vbox.g1 && rval <= vbox.g2 && + bval >= vbox.b1 && rval <= vbox.b2); + } + }; + + // Color map + function CMap() { + this.vboxes = new PQueue(function(a,b) { + return pv.naturalOrder( + a.vbox.count()*a.vbox.volume(), + b.vbox.count()*b.vbox.volume() + ) + });; + } + CMap.prototype = { + push: function(vbox) { + this.vboxes.push({ + vbox: vbox, + color: vbox.avg() + }); + }, + palette: function() { + return this.vboxes.map(function(vb) { return vb.color }); + }, + size: function() { + return this.vboxes.size(); + }, + map: function(color) { + var vboxes = this.vboxes; + for (var i=0; i 251 + var idx = vboxes.length-1, + highest = vboxes[idx].color; + if (highest[0] > 251 && highest[1] > 251 && highest[2] > 251) + vboxes[idx].color = [255,255,255]; + } + }; + + // histo (1-d array, giving the number of pixels in + // each quantized region of color space), or null on error + function getHisto(pixels) { + var histosize = 1 << (3 * sigbits), + histo = new Array(histosize), + index, rval, gval, bval; + pixels.forEach(function(pixel) { + rval = pixel[0] >> rshift; + gval = pixel[1] >> rshift; + bval = pixel[2] >> rshift; + index = getColorIndex(rval, gval, bval); + histo[index] = (histo[index] || 0) + 1; + }); + return histo; + } + + function vboxFromPixels(pixels, histo) { + var rmin=1000000, rmax=0, + gmin=1000000, gmax=0, + bmin=1000000, bmax=0, + rval, gval, bval; + // find min/max + pixels.forEach(function(pixel) { + rval = pixel[0] >> rshift; + gval = pixel[1] >> rshift; + bval = pixel[2] >> rshift; + if (rval < rmin) rmin = rval; + else if (rval > rmax) rmax = rval; + if (gval < gmin) gmin = gval; + else if (gval > gmax) gmax = gval; + if (bval < bmin) bmin = bval; + else if (bval > bmax) bmax = bval; + }); + return new VBox(rmin, rmax, gmin, gmax, bmin, bmax, histo); + } + + function medianCutApply(histo, vbox) { + if (!vbox.count()) return; + + var rw = vbox.r2 - vbox.r1 + 1, + gw = vbox.g2 - vbox.g1 + 1, + bw = vbox.b2 - vbox.b1 + 1, + maxw = pv.max([rw, gw, bw]); + // only one pixel, no split + if (vbox.count() == 1) { + return [vbox.copy()] + } + /* Find the partial sum arrays along the selected axis. */ + var total = 0, + partialsum = [], + lookaheadsum = [], + i, j, k, sum, index; + if (maxw == rw) { + for (i = vbox.r1; i <= vbox.r2; i++) { + sum = 0; + for (j = vbox.g1; j <= vbox.g2; j++) { + for (k = vbox.b1; k <= vbox.b2; k++) { + index = getColorIndex(i,j,k); + sum += (histo[index] || 0); + } + } + total += sum; + partialsum[i] = total; + } + } + else if (maxw == gw) { + for (i = vbox.g1; i <= vbox.g2; i++) { + sum = 0; + for (j = vbox.r1; j <= vbox.r2; j++) { + for (k = vbox.b1; k <= vbox.b2; k++) { + index = getColorIndex(j,i,k); + sum += (histo[index] || 0); + } + } + total += sum; + partialsum[i] = total; + } + } + else { /* maxw == bw */ + for (i = vbox.b1; i <= vbox.b2; i++) { + sum = 0; + for (j = vbox.r1; j <= vbox.r2; j++) { + for (k = vbox.g1; k <= vbox.g2; k++) { + index = getColorIndex(j,k,i); + sum += (histo[index] || 0); + } + } + total += sum; + partialsum[i] = total; + } + } + partialsum.forEach(function(d,i) { + lookaheadsum[i] = total-d + }); + function doCut(color) { + var dim1 = color + '1', + dim2 = color + '2', + left, right, vbox1, vbox2, d2, count2=0; + for (i = vbox[dim1]; i <= vbox[dim2]; i++) { + if (partialsum[i] > total / 2) { + vbox1 = vbox.copy(); + vbox2 = vbox.copy(); + left = i - vbox[dim1]; + right = vbox[dim2] - i; + if (left <= right) + d2 = Math.min(vbox[dim2] - 1, ~~(i + right / 2)); + else d2 = Math.max(vbox[dim1], ~~(i - 1 - left / 2)); + // avoid 0-count boxes + while (!partialsum[d2]) d2++; + count2 = lookaheadsum[d2]; + while (!count2 && partialsum[d2-1]) count2 = lookaheadsum[--d2]; + // set dimensions + vbox1[dim2] = d2; + vbox2[dim1] = vbox1[dim2] + 1; +// console.log('vbox counts:', vbox.count(), vbox1.count(), vbox2.count()); + return [vbox1, vbox2]; + } + } + + } + // determine the cut planes + return maxw == rw ? doCut('r') : + maxw == gw ? doCut('g') : + doCut('b'); + } + + function quantize(pixels, maxcolors) { + // short-circuit + if (!pixels.length || maxcolors < 2 || maxcolors > 256) { +// console.log('wrong number of maxcolors'); + return false; + } + + // XXX: check color content and convert to grayscale if insufficient + + var histo = getHisto(pixels), + histosize = 1 << (3 * sigbits); + + // check that we aren't below maxcolors already + var nColors = 0; + histo.forEach(function() { nColors++ }); + if (nColors <= maxcolors) { + // XXX: generate the new colors from the histo and return + } + + // get the beginning vbox from the colors + var vbox = vboxFromPixels(pixels, histo), + pq = new PQueue(function(a,b) { return pv.naturalOrder(a.count(), b.count()) }); + pq.push(vbox); + + // inner function to do the iteration + function iter(lh, target) { + var ncolors = 1, + niters = 0, + vbox; + while (niters < maxIterations) { + vbox = lh.pop(); + if (!vbox.count()) { /* just put it back */ + lh.push(vbox); + niters++; + continue; + } + // do the cut + var vboxes = medianCutApply(histo, vbox), + vbox1 = vboxes[0], + vbox2 = vboxes[1]; + + if (!vbox1) { +// console.log("vbox1 not defined; shouldn't happen!"); + return; + } + lh.push(vbox1); + if (vbox2) { /* vbox2 can be null */ + lh.push(vbox2); + ncolors++; + } + if (ncolors >= target) return; + if (niters++ > maxIterations) { +// console.log("infinite loop; perhaps too few pixels!"); + return; + } + } + } + + // first set of colors, sorted by population + iter(pq, fractByPopulations * maxcolors); + // console.log(pq.size(), pq.debug().length, pq.debug().slice()); + + // Re-sort by the product of pixel occupancy times the size in color space. + var pq2 = new PQueue(function(a,b) { + return pv.naturalOrder(a.count()*a.volume(), b.count()*b.volume()) + }); + while (pq.size()) { + pq2.push(pq.pop()); + } + + // next set - generate the median cuts using the (npix * vol) sorting. + iter(pq2, maxcolors - pq2.size()); + + // calculate the actual colors + var cmap = new CMap(); + while (pq2.size()) { + cmap.push(pq2.pop()); + } + + return cmap; + } + + return { + quantize: quantize + } +})(); \ No newline at end of file diff --git a/color-thief/sass/app.sass b/color-thief/sass/app.sass new file mode 100755 index 0000000..45c762b --- /dev/null +++ b/color-thief/sass/app.sass @@ -0,0 +1,179 @@ +@import "compass/reset" +@import "compass/css3" +@import "compass/utilities/general/clearfix" + +body, input, textarea + margin: 40px + color: #888 + background: #222 + font: 16px/1.625em "Varela Round", "lucida grande", tahoma, sans-serif + -wbkite-font-smoothing: antialiased + +h1, h2, h3, h4, h5, h6 + color: white + font-family: "Terminal Dosis", "lucida grande", tahoma, sans-serif + line-height: 1em + font-weight: 600 + margin-bottom: 0.5em + +h1 + font-size: 72px + line-height: 0.5em + margin-bottom: 0.3em + small + font-size: 20px + span + +transition( color 1s) + &:hover + .char1 + +transition( color .2s) + color: red + .char2 + +transition( color .2s .1s) + color: orange + .char3 + +transition( color .2s .2s) + color: yellow + .char4 + +transition( color .2s .3s) + color: green + .char5 + +transition( color .2s .4s) + color: blue + .char6 + +transition( color .2s .5s) + color: indigo + .char7 + +transition( color .2s .6s) + color: violet + .char8 + +transition( color .2s .7s) + color: red + .char9 + +transition( color .2s .8s) + color: orange + .char10 + +transition( color .2s .9s) + color: yellow + .char11 + +transition( color .2s 1s) + color: green + +h2 + font-size: 40px + line-height: 1.2em + text-align: center + +h3 + font-size: 16px + letter-spacing: 0.1em + text-transform: uppercase + +h4 + font-size: 20px + margin-bottom: 1.25em + +p + margin-bottom: 1.25em + + +strong + font-weight: bold + + +/* Forms */ +input + &[type=text], &[type=password] + background: #fafafa + +box-shadow(inset 0 1px 1px rgba(0, 0, 0, 0.1)) + border: 1px solid #dddddd + color: #888888 + +border-radius(4px) + +textarea + background: #fafafa + +box-shadow( inset 0 1px 1px rgba(0, 0, 0, 0.1)) + border: 1px solid #dddddd + color: #888888 + +border-radius(4px) + +input[type=text]:focus + color: #373737 + +textarea + &:focus + color: #373737 + padding-left: 3px + width: 98% + +input[type=text] + padding: 3px + + +/* Links */ +a + color: #09a1ec + text-decoration: none + &:hover + color: #7fd2fa + +#container + width: 900px + margin: 0 auto + +header + padding-bottom: 40px + text-align: center + width: 600px + margin: 0 auto + +.medianCutPalette h3 + margin-top: 20px + +.imageSection + margin-bottom: 80px + background: #111111 + +border-radius(10px) + +pie-clearfix + .imageWrap + +border-left-radius(10px) + width: 400px + height: 300px + float: left + margin-right: 20px + background: url(../img/dark_checkered_bg.png) + .targetImage + +border-left-radius(10px) + .colors + margin-top: 20px + width: 400px + float: left + .function + clear: left + margin-bottom: 10px + +pie-clearfix + .swatches .swatch + width: 40px + height: 20px + margin-right: 2px + background: #dddddd + float: left + +transition( all .5s) + &:hover + +transition( none) + +scale(1.2, 1.2) + +box-shadow( 0 1px 10px black) + &:first-child + +border-left-radius(4px) + &:last-child + +border-right-radius(4px) + +/* Hardcoding the offset for the FB icon example +.fbIcon .imageWrap .targetImage + +border-radius(0) + position: relative + top: 142px + left: 192px + +canvas + display: none \ No newline at end of file diff --git a/contributors.html b/contributors.html new file mode 100644 index 0000000..7cf4a5f --- /dev/null +++ b/contributors.html @@ -0,0 +1,29 @@ + + + + + Contributors + + + +

Contributors

+

Developers

+
    +
  • Alex Cordonnier
  • +
+

Beta testers

+
    +
  • Brian Kramer
  • +
  • Todd Hilgefort
  • +
  • Ryan Watren
  • +
  • Cole Albers
  • +
+

Translators

+

Français

+
    +
  • Alex Cordonnier
  • +
  • Léonard Nogrix
  • +
+ + + diff --git a/cws_promo/en/Screenshot from 2012-08-27 20:15:51.png b/cws_promo/en/Screenshot from 2012-08-27 20:15:51.png new file mode 100644 index 0000000..f046550 Binary files /dev/null and b/cws_promo/en/Screenshot from 2012-08-27 20:15:51.png differ diff --git a/cws_promo/en/Screenshot from 2012-08-27 20:20:32.png b/cws_promo/en/Screenshot from 2012-08-27 20:20:32.png new file mode 100644 index 0000000..edde07f Binary files /dev/null and b/cws_promo/en/Screenshot from 2012-08-27 20:20:32.png differ diff --git a/cws_promo/en/Screenshot from 2012-08-27 20:20:45.png b/cws_promo/en/Screenshot from 2012-08-27 20:20:45.png new file mode 100644 index 0000000..76c2be7 Binary files /dev/null and b/cws_promo/en/Screenshot from 2012-08-27 20:20:45.png differ diff --git a/cws_promo/en/Screenshot from 2012-08-27 20:22:13.png b/cws_promo/en/Screenshot from 2012-08-27 20:22:13.png new file mode 100644 index 0000000..285c999 Binary files /dev/null and b/cws_promo/en/Screenshot from 2012-08-27 20:22:13.png differ diff --git a/cws_promo/en/Screenshot from 2012-08-27 20:26:13.png b/cws_promo/en/Screenshot from 2012-08-27 20:26:13.png new file mode 100644 index 0000000..f87f303 Binary files /dev/null and b/cws_promo/en/Screenshot from 2012-08-27 20:26:13.png differ diff --git a/cws_promo/en_GB/Screenshot from 2012-08-27 21:19:13.png b/cws_promo/en_GB/Screenshot from 2012-08-27 21:19:13.png new file mode 100644 index 0000000..90612fb Binary files /dev/null and b/cws_promo/en_GB/Screenshot from 2012-08-27 21:19:13.png differ diff --git a/cws_promo/fr/Screenshot from 2012-08-27 21:13:12.png b/cws_promo/fr/Screenshot from 2012-08-27 21:13:12.png new file mode 100644 index 0000000..a8adc98 Binary files /dev/null and b/cws_promo/fr/Screenshot from 2012-08-27 21:13:12.png differ diff --git a/cws_promo/fr/Screenshot from 2012-08-27 21:23:12.png b/cws_promo/fr/Screenshot from 2012-08-27 21:23:12.png new file mode 100644 index 0000000..6bba21f Binary files /dev/null and b/cws_promo/fr/Screenshot from 2012-08-27 21:23:12.png differ diff --git a/cws_promo/marquee.png b/cws_promo/marquee.png new file mode 100644 index 0000000..c6cbbb1 Binary files /dev/null and b/cws_promo/marquee.png differ diff --git a/cws_promo/medium_promo.png b/cws_promo/medium_promo.png new file mode 100644 index 0000000..f90b983 Binary files /dev/null and b/cws_promo/medium_promo.png differ diff --git a/cws_promo/small_promo.png b/cws_promo/small_promo.png new file mode 100755 index 0000000..9104bd9 Binary files /dev/null and b/cws_promo/small_promo.png differ diff --git a/help.html b/help.html new file mode 100755 index 0000000..0b96f9e --- /dev/null +++ b/help.html @@ -0,0 +1,33 @@ + + + + Launchpage Help + + + + +

+
+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+
+ + + diff --git a/i18n.js b/i18n.js new file mode 100644 index 0000000..2e584ac --- /dev/null +++ b/i18n.js @@ -0,0 +1,12 @@ +//i18nize the HTML based on the i18n-content attribute +var i18n=function(){function i(b){b=b.querySelectorAll(l); +for(var d,f=0;d=b[f];f++)for(var e=0;e1;)g=g[a.shift()];if(g){g[a]=c;a=='innerHTML'&&i(b)}} +else b.setAttribute(a,c)}}}},h=[],k;for(k in j)h.push(k); +var l='['+h.join('],[')+']';return{process:i}}(); +i18n.process(document); diff --git a/icon_finder.js b/icon_finder.js new file mode 100644 index 0000000..2316d12 --- /dev/null +++ b/icon_finder.js @@ -0,0 +1,138 @@ +function findBestIcon(icons) { +//Find the highest resolution icon, then send it back to the launcher + var icon; + if (icons.length > 0) { + for (var i = 0; i < icons.length; i++) { + icons[i].sizes.sort(function(a,b){return b - a}); //Sort sizes big-small + } + icons.sort(largerIcon); + icon = icons[0].url; + } else { + icon = 'screenshot'; + } + chrome.extension.sendMessage({ + to: 'add.js', + from: 'icon_finder.js', + message: { + description: desc, + icon: icon, + title: title, + url: window.location.href + } + }); +} + +function largerIcon(a, b) { +//Sorts 2 icons by maximum size + if (!a.sizes && !b.sizes) { + return 0; + } + if (!a.sizes) { + return 1; + } + if (!b.sizes) { + return -1; + } + if (a.sizes[0] > b.sizes[0]) { + return -1; + } else if (a.sizes[0] < b.sizes[0]) { + return 1; + } else { + return 0; + } +} + +var title = document.title; +var desc = ''; +var metas = document.getElementsByTagName('meta'); +for (var i = 0; i < metas.length; i++) { //Check for meta description + if (metas[i].name == 'description') { + desc = metas[i].content; + } else if (metas[i].name == 'apple-mobile-web-app-title') { + title = metas[i].content; + } +} +if (title == '') { + title = '(Untitled)'; +} +chrome.extension.sendMessage({ //Send the title for display ASAP + to: 'add.js', + from: 'icon_finder.js', + message: {title: title} +}); +var numImgs = 0; +var links = document.getElementsByTagName('link'); +var icons = [], obj = []; +var imgs = []; //Stores icons to be checked +var imgsChecked = 0; +for (var i = 0; i < links.length; i++) { + if (links[i].rel.indexOf('icon') != -1 && + links[i].rel.indexOf('shortcut') == -1 && + links[i].href.indexOf('favicon.ico') == -1) { + //Only find icons (Apple or Opera), but not favicons + numImgs++; + checkIcon(links[i].href, true); + } +} +if (!imgs.length) searchFiles(); + +function checkIcon(url, links) { + if (!links) links = false; + obj.push({url: url}); //Start building an entry for the list of possible icons + imgs.push(new Image()); //Queue this icon to be checked + imgs[imgs.length-1].onload = function() { + obj[parseInt(this.id)].sizes = [this.width]; + if (this.width >= 57 && this.height >= 57) { //If it's not super tiny + icons.push(obj[parseInt(this.id)]); //Add to the list & keep going + } + //if (links) { //Whether it is being called by the links loop or searchFiles() + imgsChecked++; //So we know how many have been checked so far + if (imgsChecked >= numImgs) { //Are we all done? + if (!icons.length) { //If we still don't have any good icons + searchFiles(); //Look for icons in the domain's root + } else { + findBestIcon(icons); //Take what we have and find the best one + } + } + //} + } + imgs[imgs.length-1].src = url; + imgs[imgs.length-1].id = (imgs.length-1).toString(); //Keep track of each img +} +function searchFiles() { + var baseURL = window.location.origin + '/'; + var fileNames = ['apple-touch-icon.png', + 'apple-touch-icon.png-precomposed', + 'apple-touch-icon-144x144-precomposed.png', + 'apple-touch-icon-144x144.png', + 'apple-touch-icon-114x114-precomposed.png', + 'apple-touch-icon-114x114.png', + 'apple-touch-icon-72x72-precomposed.png', + 'apple-touch-icon-72x72.png', + 'apple-touch-icon-57x57-precomposed.png', + 'apple-touch-icon-57x57.png']; //These are the filenames to look for + var i = 0; + //Check to see if any Apple touch icons exist in the root of the domain + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', baseURL + fileNames[i], true); //At this point, we just want + xhr.onreadystatechange = function() { //to know if it exists or not + if (xhr.readyState == 4) { + if (xhr.status == 200) { + //Icon exists, add it to the list + numImgs++; + checkIcon(baseURL + fileNames[i]); + } + //Move on to the next icon + i++; + if (i < fileNames.length) { //Are there more to check? + xhr.open('HEAD', baseURL + fileNames[i], true); + xhr.send(); + } else { + if (icons.length == 0 && imgsChecked >= numImgs) { //Still no icons + findBestIcon(icons); //Send the extension what we do have + } + } + } + }; + xhr.send(); +} diff --git a/launcher.html b/launcher.html new file mode 100755 index 0000000..29cfdc5 --- /dev/null +++ b/launcher.html @@ -0,0 +1,16 @@ + + + + + Launchpage + + + + + + +
+
+ + + diff --git a/launcher.js b/launcher.js new file mode 100755 index 0000000..6da4b8d --- /dev/null +++ b/launcher.js @@ -0,0 +1,1044 @@ +/******************************************************************************* + * Initialize variables, classes, & prototypes + ******************************************************************************/ +var apps = []; //Array of all apps +var launcher = document.getElementById('launcher'); //The launcher element +var icons = document.createElement('div'); //Holds icons in the launcher +var isBackgroundPage = false; +var appName = (navigator.userAgent.indexOf('Chromium') == -1) ? + 'Chrome' : 'Chromium'; //Detect whether we are on Chrome or Chromium +chrome.extension.getBackgroundPage().isBackgroundPage = true; +icons.id = 'icons'; +var appTypes = { //All the Chrome addon types, plus a couple custom ones + extension: 'extension', + hostedApp: 'hosted_app', + packagedApp: 'packaged_app', + legacyPackagedApp: 'legacy_packaged_app', + theme: 'theme', + webClip: 'web_clip', + stock: 'stock' +}; + +/* From http://goo.gl/ebxrk */ +Array.prototype.move = function (old_index, new_index) { + if (new_index >= this.length) { + var k = new_index - this.length; + while ((k--) + 1) { + this.push(undefined); + } + } + this.splice(new_index, 0, this.splice(old_index, 1)[0]); +}; + +var launchpage = { //Launchpage namespace prefix + extensionInfo: {} //Will eventually contain the info about the extension +}; + +launchpage.Icon = function(id, name, url) { +//Set up the structure of the icon + var app = document.createElement('a'); + app.className = 'icon'; + app.href = url; + app.setAttribute('role', 'link'); + app.setAttribute('aria-labelledby', id + '-label'); + app.setAttribute('aria-grabbed', 'false'); + app.appendChild(document.createElement('img')); + app.appendChild(document.createElement('label')); + app.childNodes[1].id = id + '-label'; + if (id) { + app.id = id; + app.childNodes[0].src = launchpage.getAppIcon(id, 128); + } + if (name) app.childNodes[1].appendChild(document.createTextNode(name)); + + //Prevent the image and the label from being dragged separately from the icon. + //Their drag events now bubble up to the icon. + app.childNodes[0].draggable = 'false'; + app.childNodes[1].draggable = 'false'; + + app.addEventListener('dragstart', function(){ + launchpage.dragStartIcon(this); + }, false); + app.addEventListener('dragend', function(){ + launchpage.dragEndIcon(this); + }, false); + app.addEventListener('dragover', function() { + launchpage.dragOverIcon(this); + }, false); + app.addEventListener('dragenter', function(){ + launchpage.dragEnterIcon(this); + }, false); + app.addEventListener('dragleave', function(){ + launchpage.dragLeaveIcon(this); + }, false); + app.addEventListener('drop', function(){ + launchpage.dropIcon(this); + }, false); + return app; +}; + +launchpage.App = function(id, name, url) { + return { + appLaunchUrl: url, + description: '', + enabled: true, + homepageUrl: 'https://chrome.google.com/webstore/detail/' + id, + hostPermissions: [], + icons: [{ + size: 128, + url: '' + }], + id: id, + isApp: false, //deprecated + isWebClip: false, //deprecated + type: appTypes.webClip, + mayDisable: true, + name: name, + offlineEnabled: false, + optionsUrl: '', + permissions: [], + updateUrl: 'http://clients2.google.com/service/update2/crx', + version: '1.0' + }; +}; + +/******************************************************************************* + * Extension functions + ******************************************************************************/ + +launchpage.getApps = function(addons) { +//Filter out the apps from the other addons, and add prefs & store icons + for (var i in addons) { + if (addons[i].isApp || + addons[i].type == appTypes.hostedApp || + addons[i].type == appTypes.packagedApp || + addons[i].type == appTypes.legacyPackagedApp) { + apps.push(addons[i]); + } else if (addons[i].id == chrome.i18n.getMessage('@@extension_id')) { + launchpage.extensionInfo = addons[i]; + } + } + + if (apps.length == 0) + launchpage.showInfoBar(chrome.i18n.getMessage('infobarNoApps')); + + var chromePrefs = new launchpage.App('chrome-prefs', + chrome.i18n.getMessage('iconSettings'), 'chrome://settings'); + chromePrefs.description = + chrome.i18n.getMessage('iconSettingsDescription', appName); + chromePrefs.homepageUrl = ''; + chromePrefs.icons[0].url = 'skin/wrench.png'; + chromePrefs.isApp = false; + chromePrefs.type = appTypes.stock; + chromePrefs.mayDisable = false; + chromePrefs.offlineEnabled = true; + chromePrefs.updateUrl = ''; + chromePrefs.version = + navigator.appVersion.substring(navigator.appVersion.indexOf('Chrome/') + + 7, navigator.appVersion.indexOf(' ', + navigator.appVersion.indexOf('Chrome/'))); + var webStore = new launchpage.App('web-store', + chrome.i18n.getMessage('iconWebStore'), + 'https://chrome.google.com/webstore?utm_source=launchpage'); + webStore.description = chrome.i18n.getMessage('iconWebStoreDescription'); + webStore.icons[0].url = 'skin/webstore.png'; + webStore.isApp = false; + webStore.type = appTypes.stock; + webStore.mayDisable = false; + webStore.offlineEnabled = false; + webStore.updateUrl = ''; + webStore.version = ''; + + apps.push(chromePrefs, webStore); + + //Get the webclips + if (localStorage['apps']) { + storedApps = JSON.parse(localStorage['apps']); + for (var i = 0; i < storedApps.length; i++) { + if (storedApps[i].isWebClip || storedApps[i].type == appTypes.webClip) { + apps.push(storedApps[i]); + } + } + } +}; + +launchpage.checkNewApps = function() { +//Check for new apps installed & position them at the end of the list. + if (!localStorage['apps']) { + localStorage['apps'] = JSON.stringify(apps); + } else { + for (var i = 0; i < storedApps.length; i++) { //Look through saved apps + if (!apps[i] || storedApps[i].id != apps[i].id) { //If an app is misplaced + for (var j = 0; j < apps.length; j++) { //Find where it should be + if (apps[j] && storedApps[i].id == apps[j].id) { + break; + } + } + apps.move(j, i); + } + } + for (var i = 0; i < apps.length; i++) { + if (!apps[i]) { + apps.splice(i, 1); + } + } + } + localStorage['apps'] = JSON.stringify(apps); +}; + +launchpage.drawIcons = function() { //Draws icons to the page + icons.innerHTML = ''; //Clear out the icons + for (var i = 0; i < apps.length; i++) { + if (apps[i].enabled) { //If the app is enabled + launchpage.appendIcon(apps[i]); + } + } +}; + +launchpage.appendIcon = function(appObject) { +//Constructs the app object as an icon and appends it to the launcher. +//Returns true upon success. + var app = new launchpage.Icon(appObject.id, appObject.name, + appObject.appLaunchUrl); + /* + app.addEventListener('click', function(){ + event.preventDefault(); + chrome.management.launchApp(appObject.id); + window.close(); + /* + chrome.tabs.create({ + 'url': appObject.appLaunchUrl, + //'pinned': appObject.pinned + }, launchpage.appLoaded);*/ + //}, false); + if (appObject.appLaunchUrl.substring(0, 17) == 'chrome://settings') { + app.addEventListener('click', function() { + chrome.tabs.update({url: 'chrome://settings'}); + }, false); + } else if (appObject.type == appTypes.packagedApp || + appObject.type == appTypes.legacyPackagedApp) { + app.addEventListener('click', function(){ + event.preventDefault(); + chrome.management.launchApp(appObject.id); + chrome.tabs.getCurrent(function(tab) { + chrome.tabs.remove(tab.id); + }); + }, false); + } else { + //Web clip or hosted app + app.addEventListener('click', function() { + event.preventDefault(); + chrome.tabs.update({ + url: appObject.appLaunchUrl, + }); + }, false); + } + icons.appendChild(app); + return true; +}; + +launchpage.getAppById = function(id) { +//Returns an appObject that matches the id supplied. Returns null if the app +//doesn't exist or if the argument is wrong. + if (!id || typeof id != 'string') return null; + + for (var node in apps) { + if (apps[node].id == id) { + return apps[node]; + } + } + return null; +}; + +launchpage.getAppIndexById = function(id) { +//Returns the index number of the app that matches the id supplied. Returns null +//if the app doesn't exist or if the argument is wrong. + if (!id || typeof id != 'string') return null; + + var app = launchpage.getAppById(id); + for (var node = 0; node < apps.length; node++) { + if (apps[node].id == id) { + return node; + } + } + return null; +}; + +launchpage.getAppsByName = function(name) { +//Returns an array of appObjects that match the name supplied. Returns null if +//the argument is wrong. Returns an empty array if no apps match. + if (!name || typeof name != 'string') return null; + + var appsByName = [] + for (var node in apps) { + if (apps[node].name == name) { + appsByName.push(apps[node]); + } + } + return appsByName; +}; + +launchpage.getAppIcon = function(id, size) { +//Returns the URL string of the icon size belonging to the app id supplied. +//Returns undefined if the app doesn't exist or if no suitable icon is +//supplied. Returns null if an argument is wrong. + if (!id || typeof id != 'string') return null; + if (!size) size = 128; + else if (typeof size != 'number') return null; + + var app = launchpage.getAppById(id); + for (var i in app.icons) { + if (app.icons[i].size == size) { + return app.icons[i].url; + } + } + return undefined; +}; + +launchpage.dragStartIcon = function(dragSource) { + var dragIcon = document.createElement('img'); + dragIcon.src = launchpage.getAppIcon(dragSource.id); + var width = dragIcon.width/2, height = dragIcon.height/2; + if (!width) width = 64; + if (!height) height = 64; + //dragIcon.width = 128; + //dragIcon.height = 128; + event.dataTransfer.setDragImage(dragIcon, width, height); + event.dataTransfer.effectsAllowed = 'move'; + event.dataTransfer.setData('text/uri-list', dragSource.href); + event.dataTransfer.setData('text/plain', dragSource.id); + dragSource.style.opacity = '0.25'; + dragSource.setAttribute('aria-grabbed', 'true'); + var icons = launcher.childNodes[0].childNodes; + for (var i = 0; i < icons.length; i++) { + icons[i].setAttribute('aria-dropeffect', 'move'); //Mark all icons targets + } +}; + +launchpage.dragEndIcon = function(dragSource) { + dragSource.style.opacity = '1'; + dragSource.setAttribute('aria-grabbed', 'false'); +}; + +launchpage.dragOverIcon = function(dropTarget) { + event.preventDefault(); +}; + +launchpage.dragEnterIcon = function(dropTarget) { + dropTarget.classList.toggle('hover'); +}; + +launchpage.dragLeaveIcon = function(dropTarget) { + dropTarget.classList.toggle('hover'); +}; + +launchpage.dropIcon = function(dropTarget) { +//Handle icon drop reordering + event.preventDefault(); + var oldPosition = launchpage.getAppIndexById( + event.dataTransfer.getData('text/plain')); + var newPosition = launchpage.getAppIndexById(dropTarget.id); + + apps.move(oldPosition, newPosition); + launchpage.drawIcons(); + localStorage['apps'] = JSON.stringify(apps); + var icons = launcher.childNodes[0].childNodes; + for (var i = 0; i < icons.length; i++) { + icons[i].setAttribute('aria-dropeffect', 'none'); //Mark no icons targets + } +}; + +launchpage.drawContextMenu = function(event) { + //Draw the context menu based on the target type + event.preventDefault(); + + launchpage.destroyContextMenu(); + + /************************************* + * Determine the target element's type + *************************************/ + var node = event.target; + var cancelDrawing = false; //Flag to cancel drawing the context menu + if (document.getElementById('context-menu')) { //If a context menu exists + if (node.id == 'context-menu' || node.id == 'arrow' || + node.id == 'arrow-overlay') { //If the target IS the context menu + cancelDrawing = true; + } + while (!node.id && node != document) { + //Climb up the DOM tree until the node has an ID OR the node is the root + node = node.parentNode; + } + if (node.id == 'context-menu' || node.id == 'arrow' || + node.id == 'arrow-overlay') { //If the target is in the context menu + cancelDrawing = true; + } + } + while (!node.className && node != document) { + //Climb up the DOM tree until the node has a class OR the node is the root + node = node.parentNode; + } + if (node.className == 'modal-bg' || node.className == 'modalDialog') { + //If the node is a modal dialog + cancelDrawing = true; + } + if (cancelDrawing == false) { + var contextMenu = document.createElement('menu'); + contextMenu.id = 'context-menu'; + contextMenu.type = 'context'; + contextMenu.setAttribute('role', 'menu'); + var arrow = document.createElement('div'); + arrow.id = 'arrow'; + contextMenu.appendChild(arrow); + + /**************** + * Build the menu + ****************/ + switch (node.className) { + case 'icon': //If the node is an icon + var iconLi = document.createElement('li'); + iconLi.setAttribute('role', 'menuitem'); + var iconA = document.createElement('a'); + iconA.appendChild(document.createTextNode(node.innerText)); + iconA.style.fontWeight = 'bold'; + iconA.href = node.href; + if (iconA.href.substring(0, 17) == 'chrome://settings') { + iconA.addEventListener('click', function() { + chrome.tabs.update({url:'chrome://settings'}); + }, false); + } + var optionsLi = document.createElement('li'); + optionsLi.setAttribute('role', 'menuitem'); + var optionsA = document.createElement('a'); + optionsA.appendChild(document.createTextNode( + chrome.i18n.getMessage('options'))); + var app = launchpage.getAppById(node.id); + if (app.optionsUrl) { + optionsA.href = app.optionsUrl; + } else { + optionsLi.className = 'disabled'; + } + var removeLi = document.createElement('li'); + removeLi.setAttribute('role', 'menuitem'); + var removeA = document.createElement('a'); + if (app.isApp || + app.type == appTypes.hostedApp || + app.type == appTypes.packagedApp || + app.type == appTypes.legacyPackagedApp) { + removeA.appendChild(document.createTextNode( + chrome.i18n.getMessage('remove', appName))); + } else { + removeA.appendChild(document.createTextNode( + chrome.i18n.getMessage('removeWebClip'))); + } + if (app.mayDisable == true) { + removeA.href = '#'; + removeA.addEventListener('click', function(){ + document.body.removeChild( + document.getElementById('context-menu')); + if (app.isApp || + app.type == appTypes.hostedApp || + app.type == appTypes.packagedApp || + app.type == appTypes.legacyPackagedApp) { + launchpage.prompt( + chrome.i18n.getMessage('uninstallPageTitle'), + chrome.i18n.getMessage('uninstallApp', app.name), + function() { + chrome.management.uninstall( + app.id, + window.location.reload()); + }, + chrome.i18n.getMessage('buttonUninstall'), + node.childNodes[0].src); + } else { + launchpage.prompt( + chrome.i18n.getMessage('removePageTitle'), + chrome.i18n.getMessage('removeWebClipMessage', app.name), + function() { + var index = launchpage.getAppIndexById(app.id); + apps.splice(index, 1); + localStorage['apps'] = JSON.stringify(apps); + window.location.reload(); + }, + chrome.i18n.getMessage('buttonRemove'), + node.childNodes[0].src); + } + }, false); + } else { + removeLi.className = 'disabled'; + } + + iconLi.appendChild(iconA); + optionsLi.appendChild(optionsA); + removeLi.appendChild(removeA); + contextMenu.appendChild(iconLi); + if (removeLi.className != 'disabled') { + contextMenu.appendChild(document.createElement('hr')); + contextMenu.childNodes[2].setAttribute('role', 'separator'); + } + if (optionsLi.className != 'disabled') { + contextMenu.appendChild(optionsLi); + } + if (removeLi.className != 'disabled') { + contextMenu.appendChild(removeLi); + } + + break; + + default: //If the node isn't any of the above (e.g. the root element) + var launchpageLi = document.createElement('li'); + var launchpageA = document.createElement('a'); + launchpageA.appendChild(document.createTextNode( + chrome.i18n.getMessage('extName'))); + launchpageA.style.fontWeight = 'bold'; + launchpageLi.setAttribute('role', 'menuitem'); + if (launchpage.extensionInfo.homepageUrl) { + launchpageA.href = launchpage.extensionInfo.homepageUrl; + } else { + launchpageLi.className = 'disabled'; + } + var prefsLi = document.createElement('li'); + prefsLi.setAttribute('role', 'menuitem'); + var prefsA = document.createElement('a'); + prefsA.appendChild(document.createTextNode( + chrome.i18n.getMessage('options'))); + prefsA.href = 'prefs.html'; + + var manageLi = document.createElement('li'); + manageLi.setAttribute('role', 'menuitem'); + var manageA = document.createElement('a'); + manageA.appendChild(document.createTextNode( + chrome.i18n.getMessage('manageExtensions'))); + manageA.href = 'chrome://extensions'; + manageA.addEventListener('click', function() { + chrome.tabs.update({url:'chrome://extensions'}); + }, false); + + launchpageLi.appendChild(launchpageA); + prefsLi.appendChild(prefsA); + manageLi.appendChild(manageA); + contextMenu.appendChild(launchpageLi); + contextMenu.appendChild(document.createElement('hr')); + contextMenu.childNodes[2].setAttribute('role', 'separator'); + contextMenu.appendChild(prefsLi); + contextMenu.appendChild(manageLi); + break; + } + + //Enables the context menu to have its style calculated - necessary for + //position calculations + contextMenu.style.display = 'block'; + document.body.appendChild(contextMenu); + + /********************************************* + * Context menu & triangle metrics - calculate + * position to display menu & arrow + *********************************************/ + switch (node.className) { + case 'icon': + //if the target is an icon, display the context menu below the icon + + node.focus(); //Set the focus to the icon as visual feedback + + //Make the arrow display on top of the context menu + arrow.className = 'top'; + + //Center the context menu horizontally on the icon + contextMenu.style.left = node.offsetLeft + + (parseInt(getComputedStyle(node)['width']) + + parseInt(getComputedStyle(node)['padding-left']) + + parseInt(getComputedStyle(node)['padding-right']) - + parseInt(getComputedStyle(contextMenu)['width']))/2 + 'px'; + + //Position the context menu below the icon + contextMenu.style.top = node.offsetTop - + parseInt(getComputedStyle(arrow)['top']) + + parseInt(getComputedStyle(node)['height']) + + parseInt(getComputedStyle(node)['padding-top']) + + parseInt(getComputedStyle(node)['padding-bottom']) + 'px'; + + //Center the arrow horizontally on the menu + arrow.style.left = + (parseInt(getComputedStyle(contextMenu)['width']) + + parseInt(getComputedStyle(contextMenu)['padding-left']) + + parseInt(getComputedStyle(contextMenu)['padding-right']))/2 + + parseInt(getComputedStyle(arrow)['top']) + 'px'; + + if (parseInt(contextMenu.style.top) + + parseInt(getComputedStyle(contextMenu)['padding-top']) + + parseInt(getComputedStyle(contextMenu)['padding-bottom']) + + parseInt(getComputedStyle(contextMenu)['height']) - + document.body.scrollTop > window.innerHeight) { + //if the context menu overflows the viewport vertically + + arrow.className = 'bottom'; //Make the arrow show below the menu + + //Position the context menu above the icon + contextMenu.style.top = node.offsetTop + + parseInt(getComputedStyle(arrow)['bottom']) - + parseInt(getComputedStyle(contextMenu)['height']) - + parseInt(getComputedStyle(contextMenu)['padding-top']) - + parseInt(getComputedStyle(contextMenu)['padding-bottom']) + + 'px'; + } + break; + + default: + //if the target is not an icon, display the context menu with the arrow + //tip at the point clicked + + //Make the arrow display on the left side of the menu + arrow.className = 'left'; + //Center the arrow vertically on the first menu item + arrow.style.top = + (parseInt(getComputedStyle( + contextMenu.getElementsByTagName('li')[0])['height']) + + 2 * parseInt(getComputedStyle(arrow)['left']) + 1)/2 + + parseInt(getComputedStyle(contextMenu)['padding-top']) + 'px'; + + contextMenu.style.left = event.pageX - + parseInt(getComputedStyle(arrow)['left']) - 1 + 'px'; + contextMenu.style.top = event.pageY + + parseInt(getComputedStyle(arrow)['left']) - + parseInt(getComputedStyle(arrow)['top']) + 'px'; + + if (parseInt(getComputedStyle(contextMenu)['left']) + + parseInt(getComputedStyle(contextMenu)['width']) > + window.innerWidth) { + //If the menu overflows the window horizontally, make the arrow + //display on the right side of the menu + arrow.className = 'right'; + //Center the arrow vertically on the first menu item + arrow.style.top = + (parseInt(getComputedStyle( + contextMenu.getElementsByTagName('li')[0])['height']) + + 2 * parseInt(getComputedStyle(arrow)['right']) + 2)/2 + + parseInt(getComputedStyle(contextMenu)['padding-top']) + 'px'; + + contextMenu.style.left = event.pageX - + parseInt(getComputedStyle(contextMenu)['width']) + + parseInt(getComputedStyle(arrow)['right']) + 'px'; + contextMenu.style.top = event.pageY + + parseInt(getComputedStyle(arrow)['right']) - + parseInt(getComputedStyle(arrow)['top']) + 'px'; + } + + break; + } + } + return true; +}; + +launchpage.destroyContextMenu = function() { +//Destroys the context menu when the user clicks outside of the menu + if (document.getElementById('context-menu')) { + if (event.target == document.childNodes[1]) { //If it's the root element + document.body.removeChild(document.getElementById('context-menu')); + return true; + } else if (event.target.id != 'context-menu' && + event.target.parentNode.id != 'context-menu' && + event.target.parentNode.parentNode.id != 'context-menu') { + document.body.removeChild(document.getElementById('context-menu')); + return true; + } + } + return false; +}; + +launchpage.prompt = function(titleText, text, buttonAction, buttonLabel, iconUrl) { +//Displays a modal prompt + if (!buttonAction) { + buttonAction = function(){ + overlay.style.opacity = '0'; + //Give the prompt time to fade out + window.setTimeout(function(){document.body.removeChild(overlay)}, 500); + }; + } + buttonLabel = buttonLabel ? buttonLabel : 'OK'; + //Create the prompt + var overlay = document.createElement('div'); + overlay.className = 'overlay'; + overlay.style.opacity = '0'; + var page = document.createElement('div'); + page.className = 'page'; + page.setAttribute('role', 'dialog'); + var title = document.createElement('h1'); + title.appendChild(document.createTextNode(titleText)); + title.id = 'modal-title'; + page.setAttribute('aria-labelledby', 'modal-title'); + var contentArea = document.createElement('div'); + contentArea.className = 'content-area'; + contentArea.id = 'modal-content'; + page.setAttribute('aria-describedby', 'modal-content'); + if (iconUrl) { + var icon = document.createElement('img'); + icon.src = iconUrl; + } + var label = document.createElement('label'); + label.appendChild(document.createTextNode(text)); + var actionArea = document.createElement('div'); + actionArea.className = 'action-area'; + var buttonStrip = document.createElement('div'); + buttonStrip.className = 'button-strip'; + var cancelButton = document.createElement('button'); + cancelButton.appendChild(document.createTextNode( + chrome.i18n.getMessage('buttonCancel'))); + cancelButton.type = 'reset'; + cancelButton.addEventListener('click', function(){ + overlay.style.opacity = '0'; + //Give the prompt time to fade out + window.setTimeout(function(){document.body.removeChild(overlay)}, 500); + }, false); + var mainButton = document.createElement('button'); + mainButton.appendChild(document.createTextNode(buttonLabel)); + mainButton.type = 'submit'; + mainButton.addEventListener('click', buttonAction, false); + + if (iconUrl) contentArea.appendChild(icon); + contentArea.appendChild(label); + buttonStrip.appendChild(cancelButton); + buttonStrip.appendChild(mainButton); + actionArea.appendChild(buttonStrip); + page.appendChild(title); + page.appendChild(contentArea); + page.appendChild(actionArea); + overlay.appendChild(page); + document.body.appendChild(overlay); + //Give the prompt time to fade in + window.setTimeout(function(){overlay.style.opacity = '1'}, 10); + + return true; +}; + +launchpage.showInfoBar = function(message, bgColor, textColor) { +//Displays an info bar with a message. Optionally set a hex bg & text color. + if (document.getElementById('infobar')) { + document.body.removeChild(document.getElementById('infobar')); + } + var infobar = document.createElement('div'); + infobar.id = 'infobar'; + infobar.innerText = message; + infobar.innerHTML += '  ' + + chrome.i18n.getMessage('infobarClose') + ''; + infobar.setAttribute('role', 'status'); + infobar.setAttribute('aria-describedby', 'infobar'); + if (bgColor) { //Calculate the gradient for the background + var darkBgColor = ''; + bgColor = bgColor.replace('#', ''); + if ((bgColor.length == 6 || bgColor.length == 3) && + !isNaN(parseInt(bgColor, 16))) { //Make sure it's a valid hex code + if (bgColor.length == 3) { + codes = [bgColor.substring(0,1), + bgColor.substring(1,2), + bgColor.substring(2,3)]; + bgColor = codes[0] + codes[0] + + codes[1] + codes[1] + + codes[2] + codes[2]; + } + var rgb = [parseInt(bgColor.substring(0, 2), 16), + parseInt(bgColor.substring(2, 4), 16), + parseInt(bgColor.substring(4, 6), 16)]; + for (var i = 0; i < rgb.length; i++) { + if (rgb[i] < 34) { + darkBgColor += '00'; + } else { + darkBgColor += (rgb[i] - 34).toString(16); + } + } + infobar.style.background = '-webkit-linear-gradient(#' + bgColor + + ', #' + darkBgColor + ')'; + } else { + console.error('Invalid color code passed to launchpage.showInfoBar'); + } + } else { + infobar.style.background = '-webkit-linear-gradient(#ddd, #bbb)'; + } + if (textColor) { + infobar.style.color = textColor; + } else { + infobar.style.color = '#000'; + } + document.body.appendChild(infobar); + document.getElementById('infobarClose').addEventListener('click', + launchpage.hideInfoBar, false); + return true; +}; + +launchpage.hideInfoBar = function() { + if (document.getElementById('infobar')) { + document.body.removeChild(document.getElementById('infobar')); + return true; + } else { + return false; + } +}; + +launchpage.offLine = function() { +//Make offline apps stand out by making other apps transparent + if (localStorage['infobarOffline'] != 'true') { + launchpage.showInfoBar(chrome.i18n.getMessage('infobarOffline')); + localStorage['infobarOffline'] = 'true'; + } + var icons = document.getElementById('icons').childNodes; + for (var i = 0; i < apps.length; i++) { + if (!apps[i].offlineEnabled && apps[i].enabled) { + //If the app is not offline-enabled + icons[i].style.opacity = '0.25'; + } + } +}; + +launchpage.onLine = function() { +//Reset apps opacity to make them opaque again + launchpage.hideInfoBar(); + var icons = document.getElementById('icons').childNodes; + for (var i = 0; i < apps.length; i++) { + icons[i].style.opacity = '1.0'; + } +}; + +launchpage.rgbToHsl = function(rgb){ + var r = rgb[0], g = rgb[1], b = rgb[2]; + r /= 255, g /= 255, b /= 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2; + + if (max == min) { + h = s = 0; //achromatic + } else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return [h,s,l]; +} + +function injectContentScript(tabId, changeInfo, tab) { + if (changeInfo.status == 'complete' && tab.url.substring(0,4) == 'http') { + chrome.tabs.executeScript(tabId, {file: 'chrome-webstore-item_finder.js'}); + } +} + +//Page action stuff +function checkUrl(tabId, changeInfo, tab) { +//Check whether the URL is valid + if (localStorage['page-action'] == 'true' && + tab.url.substring(0, 34) != 'https://chrome.google.com/webstore' && + (tab.url.substring(0, 7) == 'http://' || + tab.url.substring(0, 8) == 'https://')) { //If URL is valid + chrome.pageAction.show(tabId); //Show the page action + } else { + chrome.pageAction.hide(tabId); + } +} + +function setUpCurrentTabs() { + chrome.tabs.query({}, function(tabs) { //Get all tabs + for (var i = 0; i < tabs.length; i++) { + checkUrl(tabs[i].id, {}, tabs[i]); + } + }); +} + +function errorHandler(e) { + var msg = ''; + switch (e.code) { + case FileError.QUOTA_EXCEEDED_ERR: + msg = 'QUOTA_EXCEEDED_ERR'; + break; + case FileError.NOT_FOUND_ERR: + msg = 'NOT_FOUND_ERR'; + break; + case FileError.SECURITY_ERR: + msg = 'SECURITY_ERR'; + break; + case FileError.INVALID_MODIFICATION_ERR: + msg = 'INVALID_MODIFICATION_ERR'; + break; + case FileError.INVALID_STATE_ERR: + msg = 'INVALID_STATE_ERR'; + break; + default: + msg = 'Unknown Error'; + break; + }; + console.error(msg); +} + +launchpage.addToHomeScreen = function(details) { + //Builds an App object, then adds it to the list of apps. Used for web clips. + if (isBackgroundPage) { + //Only add it if it's the background page. Otherwise, if Launchpage is open + //somewhere else, it would fire multiple times. + var app = new launchpage.App(details.id, details.title, details.url); + app.homepageUrl = details.url; + app.icons[0].url = details.icon; + app.updateUrl = ''; + app.isApp = false; + app.isWebClip = true; + app.type = appTypes.webClip; + //FIXME? The background page doesn't get updates when apps/webclips are + //removed. It only loads the app list on startup. Therefore, we need to + //refresh its copy of the apps variable from localStorage (which is updated). + apps = JSON.parse(localStorage['apps']); + apps.push(app); + localStorage['apps'] = JSON.stringify(apps); + chrome.tabs.create({}); + } +}; + +/******************************************************************************* + * Event listeners + ******************************************************************************/ + +//Inject the content script to look for chrome-webstore-item +//Disabled because the infobar API is still experimental +//chrome.tabs.onUpdated.addListener(injectContentScript); + +//Listen for tab updates so we can check the URL for the page action +if (localStorage['page-action'] == 'true') { + chrome.tabs.onUpdated.addListener(checkUrl); //Listen for tab updates +} + +//Draw Launchpage context menu instead of the browser's +document.addEventListener('contextmenu', launchpage.drawContextMenu, false); + +//Destroy the context menu when the user clicks anywhere outside of the menu +document.addEventListener('mousedown', launchpage.destroyContextMenu, false); + +window.addEventListener('load', function(e) { + //Append icons to the launcher + launcher.appendChild(icons); + + //Check if a new cache is available on page load + window.applicationCache.addEventListener('updateready', function(e) { + if (window.applicationCache.status == window.applicationCache.UPDATEREADY) { + window.applicationCache.swapCache(); + } + }, false); + window.setTimeout(function() { + console.log('Page load time:', + performance.timing.loadEventEnd - performance.timing.navigationStart, + 'ms'); + }, 100); +}, false); + +chrome.extension.onMessage.addListener(function (msg, sender) { + if (msg.to == 'launcher.js' && msg.from == 'add.js') { + //It's being sent to the background page from the page action + launchpage.addToHomeScreen(msg.message); //Add the icon to the home screen + } else if (msg.to == 'launcher.js' && + msg.from == 'chrome-webstore-item_finder.js') { + //Sent from the webstore content script to the background page + //First, check if the infobar has already been disabled for this page + console.log('infobar.hide.' + msg.message.url); + console.log(localStorage['infobar.hide.' + msg.message.url]); + if (localStorage['infobar.hide.' + msg.message.url] != 'true') { + //Show the infobar + chrome.experimental.infobars.show({ + path: 'chrome-webstore-item.html#' + escape(msg.message.url) + + '&' + escape(msg.message.host), + tabId: sender.tab.id + }); + } + } +}); + +//Make the icons fade when connectivity is lost +window.addEventListener('offline', launchpage.offLine, false); +window.addEventListener('online', launchpage.onLine, false); + +/******************************************************************************* + * Post scripts + ******************************************************************************/ + +//Request addons list from chrome - includes apps, extensions, & themes (these +//will be filtered out in getApps() +chrome.management.getAll(function(addons) { + launchpage.getApps(addons); + launchpage.checkNewApps(); + launchpage.drawIcons(); + if (!navigator.onLine) launchpage.offLine(); +}); + +//Set the background +if (localStorage['background'] == 'bg-custom') { + document.body.style.backgroundImage = + 'url(' + localStorage['background-image-url'] + ')'; +} else if (localStorage['background'] == 'bg-color') { + document.body.style.backgroundColor = localStorage['background-color']; +} else { + document.body.style.backgroundImage = + "-webkit-radial-gradient(center, ellipse cover, #ccc, #666)"; +} + +//Adjust the color palette based on the dominant color of the background +if (localStorage['background'] == 'bg-custom') { + var dominantColor = + JSON.parse(localStorage['background-dominant-color']); + if (launchpage.rgbToHsl(dominantColor)[2] > 0.5) { + document.styleSheets[0].addRule('.icon > label', 'color: #000'); + document.styleSheets[0].addRule('.icon > label', + 'text-shadow: #fff 0 0 10px, #fff 0 0 10px,' + + '#fff 0 0 10px, #fff 0 0 10px, #fff 0 0 10px'); + if (localStorage['chameleon'] == 'true') { + document.styleSheets[0].addRule('#context-menu', 'color: #000'); + document.styleSheets[0].addRule('#context-menu li.disabled', + 'color: rgba(0, 0, 0, 0.25)'); + } + } + if (localStorage['chameleon'] == 'true') { + var secondaryColor = + JSON.parse(localStorage['background-secondary-color']); + var colors = JSON.parse(localStorage['background-colors']); + var rgb = colors[0]; + var rgbLight = colors[1]; + var rgbMed = colors[2]; + var rgbDark = colors[3]; + var rgb2 = colors[4]; + document.styleSheets[0].addRule('.icon:hover, .icon:focus, .icon.hover', + 'background: rgba(' + rgb[0] + ', ' + rgb[1] + ', ' + rgb[2] + ', 0.5)'); + document.styleSheets[0].addRule('#context-menu', + 'background: -webkit-linear-gradient(' + + 'rgba('+rgbLight[0]+', '+rgbLight[1]+', '+rgbLight[2]+', 0.9),'+ + 'rgba('+rgbDark[0]+', '+rgbDark[1]+', '+rgbDark[2]+', 0.9))'); + document.styleSheets[0].addRule('#context-menu > #arrow.top', + 'border-bottom: 12px solid rgba(' + rgbLight[0] + ', '+ + rgbLight[1] + ', ' + rgbLight[2] + ', 0.9)'); + document.styleSheets[0].addRule('#context-menu > #arrow.left', + 'border-right: 12px solid rgba(' + rgbMed[0] + ', '+ + rgbMed[1] + ', ' + rgbMed[2] + ', 0.9)'); + document.styleSheets[0].addRule('#context-menu > #arrow.right', + 'border-left: 12px solid rgba(' + rgbMed[0] + ', '+ + rgbMed[1] + ', ' + rgbMed[2] + ', 0.9)'); + document.styleSheets[0].addRule('#context-menu > #arrow.bottom', + 'border-top: 12px solid rgba(' + rgbDark[0] + ', '+ + rgbDark[1] + ', ' + rgbDark[2] + ', 0.9)'); + document.styleSheets[0].addRule('#context-menu li:not(.disabled):hover > a,' + + '#context-menu li:not(.disabled) > a:focus', + 'background:rgba(' + rgb2[0] + ',' + rgb2[1] + ',' + rgb2[2] + ', .75)'); + if (launchpage.rgbToHsl(secondaryColor)[2] > 0.5) { + document.styleSheets[0].addRule( + '#context-menu li:not(.disabled):hover > a,' + + '#context-menu li:not(.disabled) > a:focus', + 'color: #000'); + } else { + document.styleSheets[0].addRule( + '#context-menu li:not(.disabled):hover > a,' + + '#context-menu li:not(.disabled) > a:focus', + 'color: #fff'); + } + } +} + +//Display page action on tabs +setUpCurrentTabs(false); + +//Initiate settings +if (!localStorage['background']) localStorage['background'] = 'bg-default'; +if (!localStorage['chameleon']) localStorage['chameleon'] = 'true'; +if (!localStorage['page-action']) localStorage['page-action'] = 'true'; diff --git a/launchpage.appcache b/launchpage.appcache new file mode 100755 index 0000000..f5e96ee --- /dev/null +++ b/launchpage.appcache @@ -0,0 +1,23 @@ +CACHE MANIFEST +#v1.1 + +#Cache common files +CACHE: +launcher.html +prefs.html +add.html +/_locales/en/messages.json +/_locales/fr/messages.json +skin/launcher.css +skin/popup.css +skin/prefs/button.css +skin/prefs/page_legacy.css +skin/favicon.ico +launcher.js +prefs.js +add.js +i18n.js + +#NETWORK: +#http://www.google-analytics.com +#https://ssl.google-analytics.com diff --git a/manifest.json b/manifest.json new file mode 100755 index 0000000..5f63bf4 --- /dev/null +++ b/manifest.json @@ -0,0 +1,34 @@ +{ + "name": "__MSG_extName__", + "version": "1.1.7", + "manifest_version": 2, + "description": "__MSG_extDescription__", + "default_locale": "en", + "background": { + "page": "launcher.html" + }, + "options_page": "prefs.html", + "incognito": "spanning", + "offline_enabled": true, + "chrome_url_overrides": { + "newtab": "launcher.html" + }, + "permissions": [ + "management", + "tabs", + "", + "storage", + "unlimitedStorage" + ], + "icons": { + "128": "skin/icon_128.png", + "48": "skin/icon_48.png", + "32": "skin/icon_32.png", + "16": "skin/icon_16.png" + }, + "page_action": { + "default_icon": "skin/icon_19.png", + "default_title": "Add to Launchpage", + "default_popup": "add.html" + } +} diff --git a/prefs.html b/prefs.html new file mode 100755 index 0000000..917b805 --- /dev/null +++ b/prefs.html @@ -0,0 +1,134 @@ + + + + + Options + + + + + + + + + + + + + + +
+ +
+
+
+
+

+
+
+

+
+ + +
+
+
+
+
+
+ +
+
+
+

+
+ +
+
+
+
+
+

+
+
+

+
+ + +
+
+
+ + +
+
+
+
+
+
+
+ + + + + + + diff --git a/prefs.js b/prefs.js new file mode 100755 index 0000000..7a908dc --- /dev/null +++ b/prefs.js @@ -0,0 +1,334 @@ +/******************************************************************************* + * Declare variables + ******************************************************************************/ +var launchpage = chrome.extension.getBackgroundPage().launchpage; +var fs, bgThumb; + +/******************************************************************************* + * Option functions + ******************************************************************************/ +function loadPage(page) { //Switch to the specified page + if (!page) { + if (localStorage['optionsPage']) + page = localStorage['optionsPage']; + else + page = 'general'; + } + var navbarItems = document.getElementsByClassName('navbar-item'); + for (var i = 0; i < navbarItems.length; i++) { + navbarItems[i].classList.remove('navbar-item-selected'); + } + var pages = document.getElementsByClassName('page'); + for (var i = 0; i < pages.length; i++) { + pages[i].style.display = 'none'; + } + document.getElementById(page + 'Page').style.display = 'block'; + document.getElementById(page + 'PageNav').classList.add( + 'navbar-item-selected'); + localStorage['optionsPage'] = page; +} + +function loadPrefs(bgDir) { +//Load the saved settings and display them + document.getElementById('chameleon').checked = + (localStorage['chameleon'] == 'true'); + document.getElementById('page-action').checked = + (localStorage['page-action'] == 'true'); + if (localStorage['background-image-url']) { + //Display the saved background thumbnails + var dirReader = bgDir.createReader(); + dirReader.readEntries(function(entries) { + for (var i = 0, entry; entry = entries[i]; ++i) { + if (entry.isFile) { + appendThumb(entry.toURL()); + if (localStorage['background'] == 'bg-custom' && + localStorage['background-image-url'] == entry.toURL()) { + setSelected(document.getElementById(entry.toURL())); + } + } + } + }, errorHandler); + } + + var bg = document.getElementsByName('background'); + for (var i in bg) { + if (bg[i].id == localStorage['background']) { + bg[i].checked = 'true'; + } + } +} + +function save(pref) { //Autosave the setting that was just changed + switch (pref.name) { + case 'background': + if (pref.id == 'bg-default') { + localStorage['background'] = 'bg-default'; + localStorage['background-dominant-color'] = '#000000'; + } else { + localStorage['background'] = 'bg-custom'; + localStorage['background-image-url'] = pref.id; + bgThumb = pref.id; + window.setTimeout(function() { + setColors(bgThumb + '-thumb'); + }, 1000); + } + break; + case 'background-image': + var file = event.target.files[0]; + if (!file.type.match('image.*')) { + alert('The file you selected is not an image. Please retry and select' + + ' an image file.'); + break; + } + writeFile(file); + break; + case 'chameleon': + localStorage['chameleon'] = pref.checked; + break; + case 'page-action': + localStorage['page-action'] = pref.checked; + chrome.extension.getBackgroundPage().setUpCurrentTabs(); + break; + } +} + +function errorHandler(e) { + var msg = ''; + switch (e.code) { + case FileError.QUOTA_EXCEEDED_ERR: + msg = 'QUOTA_EXCEEDED_ERR'; + break; + case FileError.NOT_FOUND_ERR: + msg = 'NOT_FOUND_ERR'; + break; + case FileError.SECURITY_ERR: + msg = 'SECURITY_ERR'; + break; + case FileError.INVALID_MODIFICATION_ERR: + msg = 'INVALID_MODIFICATION_ERR'; + break; + case FileError.INVALID_STATE_ERR: + msg = 'INVALID_STATE_ERR'; + break; + default: + msg = 'Unknown Error'; + break; + }; + console.error(msg); +} + +function writeFile(f) { //Write the background image to the filesystem + fs.root.getFile('backgrounds/' + f.name, {create: true, exclusive: false}, + function(fileEntry) { + fileEntry.createWriter(function(fileWriter) { + fileWriter.onwriteend = function(e) { + localStorage['background'] = 'bg-custom'; + localStorage['background-image-url'] = fileEntry.toURL(); + appendThumb(fileEntry.toURL()); + setSelected(document.getElementById(fileEntry.toURL())); + }; + fileWriter.onerror = function(e) { + console.error('Write failed: ' + e.toString()); + }; + fileWriter.write(f); + }, errorHandler); + }, errorHandler); +} + +function appendThumb(url) { +//Display the saved background thumbnail + var mainDiv = document.createElement('div'); + var secondDiv = document.createElement('div'); + var bgImg = document.createElement('img'); + var deleteButton = document.createElement('button'); + + mainDiv.id = url; + mainDiv.name = 'background'; + mainDiv.className = 'deletable-item'; + mainDiv.setAttribute('role', 'option'); + mainDiv.lead = 'lead'; + mainDiv.setAttribute('aria-selected', 'false'); + mainDiv.addEventListener('click', function(){setSelected(this)}, false); + mainDiv.addEventListener('mouseover', function() { + this.childNodes[1].style.backgroundColor = '#fff'; + }, false); + mainDiv.addEventListener('mouseout', function() { + this.childNodes[1].style.backgroundColor = 'transparent'; + }, false); + bgImg.src = url; + bgImg.className = 'bg-thumb'; + bgImg.id = url + '-thumb'; + deleteButton.className = 'raw-button row-delete-button custom-appearance'; + deleteButton.addEventListener('click', function(){ + removeThumb(this); + event.stopPropagation(); + }, false); + + secondDiv.appendChild(bgImg); + mainDiv.appendChild(secondDiv); + mainDiv.appendChild(deleteButton); + document.getElementById('backgrounds-grid').appendChild(mainDiv); +} + +function removeThumb(element) { + var thumbDiv = element.parentNode; + fs.root.getFile(decodeURI(thumbDiv.id.substring(74)), {create: false}, + function (bgFile) { + bgFile.remove(function() {}, errorHandler); + }, errorHandler); + if (thumbDiv.getAttribute('selected') == 'selected') { + setSelected(document.getElementById('bg-default')); + } + thumbDiv.parentNode.removeChild(thumbDiv); +} + +function setColors(img) { +//Get palette & dominant color in background image + var dominantColor = getDominantColor(document.getElementById(img)); + localStorage['background-dominant-color'] = '[' + dominantColor + ']'; + var palette = createPalette(document.getElementById(img), 5); + var secondaryColor; + for (var i = palette.length - 1; i >= 0; i--) { + var difference = [0, 0, 0]; + for (var j = 0; j < 3; j++) { + difference[j] = Math.abs(dominantColor[j] - palette[i][j]); + } + if (difference[0] > 50 || difference[1] > 50 || difference[2] > 50) { + secondaryColor = palette[i]; + } + } + localStorage['background-secondary-color'] = '[' + secondaryColor + ']'; + var colors = [adjustRGB(dominantColor, -30), adjustRGB(dominantColor, -20), + adjustRGB(dominantColor, -28), adjustRGB(dominantColor, -70), + adjustRGB(secondaryColor, 0)]; + var paletteString = '['; + for (var i = 0; i < colors.length; i++) { + if (i > 0) { + paletteString += ','; + } + paletteString += '[' + colors[i] + ']'; + } + paletteString += ']'; + localStorage['background-colors'] = + paletteString; +} + +function setSelected(element) { + document.getElementById('bg-default').removeAttribute('selected'); + document.getElementById('bg-default').setAttribute('aria-selected', 'false'); + var items = document.getElementsByClassName('deletable-item'); + for (var i = 0; i < items.length; i++) { + if (items[i].getAttribute('selected')) { + items[i].removeAttribute('selected'); + items[i].setAttribute('aria-selected', 'false'); + } + } + element.setAttribute('selected', 'selected'); + element.setAttribute('aria-selected', 'true'); + save(element); +} + +function adjustRGB(rgb, amount) { + if (amount == 0) { + return rgb; + } + var ret = [0, 0, 0]; + for (var i = 0; i < ret.length; i++) { + ret[i] = rgb[i] + amount; + if (ret[i] < 0) { + ret[i] = 0; + } else if (ret[i] > 255) { + ret[i] = 255; + } + } + return ret; +} + +function differenceRGB(rgb1, rgb2) { + var ret = [0, 0, 0]; + for (var i = 0; i < ret.length; i++) { + ret[i] = Math.abs(rgb1[i] - rgb2[i]); + } + return ret; +} + +/******************************************************************************* + * Event listeners + ******************************************************************************/ +var navbarItems = document.getElementsByClassName('navbar-item'); +for (var i = 0; i < navbarItems.length; i++) { + if (navbarItems[i].id != 'searchPageNav') { + navbarItems[i].addEventListener('click', function() { + loadPage(this.getAttribute('pagename')); + }, false); + } +} +document.getElementById('background-image').addEventListener('change', + function() { save(this) }, false); +document.getElementById('bg-default').addEventListener('click', function(){ + setSelected(this); +}, false); +document.getElementById('chameleon').addEventListener('change', function() { + save(this); +}, false); +document.getElementById('page-action').addEventListener('change', function() { + save(this); +}, false); +document.getElementById('getHelpButton').addEventListener('click', function() { + window.open('help.html'); +}, false); +document.getElementById('reportProblemButton').addEventListener('click', + function() { + window.location.href = + 'https://chrome.google.com/webstore/support/' + + launchpage.extensionInfo.id + '#bug'; + }, false); + +/******************************************************************************* + * Post scripts + ******************************************************************************/ +//Webkit-specific requestFileSystem +window.requestFileSystem = window.requestFileSystem || + window.webkitRequestFileSystem; + +//FIXME: Don't know why this resets, as it is declared in the HTML, but whatever +document.getElementById('bg-default').name = 'background'; + +//Display extension info in Help tab +document.getElementById('version').innerText = chrome.i18n.getMessage( + 'optionsVersion', launchpage.extensionInfo.version); +document.getElementById('aboutIcon').src = + launchpage.extensionInfo.icons[3].url; +document.getElementById('copyright').innerText = chrome.i18n.getMessage( + 'optionsCopyright', new Date().getFullYear().toString()); + +//Filesystem directory writer adapted from http://www.html5rocks.com +window.webkitStorageInfo.requestQuota(PERSISTENT, 1024*100, //100 MB + function(grantedBytes) { + window.requestFileSystem(PERSISTENT, grantedBytes, function(fsys) { + (function() { + fs = fsys; + fs.root.getDirectory( + 'backgrounds', + {}, //read directory (not write) + function(dir) { //directory exists + loadPrefs(dir); + }, + function() { //directory doesn't exist + fs.root.getDirectory( + 'backgrounds', + {create: true}, //create the directory + function(dir) { + loadPrefs(dir); + }, + errorHandler + ); + } + ); + })(); + }, errorHandler); + }, errorHandler); +loadPage(); + +//Use Chrome's OS detector script to enable platform-specific CSS +//cr.enablePlatformSpecificCSSRules(); diff --git a/skin/contributors.css b/skin/contributors.css new file mode 100644 index 0000000..f7c3481 --- /dev/null +++ b/skin/contributors.css @@ -0,0 +1,27 @@ +body { + background-color: #f1f1f1; + color: #333; + font-family: Helvetica, Arial, sans-serif; + margin: 24px; + text-shadow: white 0 1px 2px; +} + +h1, h2, h3 { + font-weight: normal; +} + +h2 { + margin-left: 24px; +} + +h3, ul { + margin-left: 48px; +} + +ul { + padding-left: 16px; +} + +li { + list-style-type: circle; +} diff --git a/skin/favicon.ico b/skin/favicon.ico new file mode 100755 index 0000000..0f75de6 Binary files /dev/null and b/skin/favicon.ico differ diff --git a/skin/help.css b/skin/help.css new file mode 100644 index 0000000..4290f3b --- /dev/null +++ b/skin/help.css @@ -0,0 +1,19 @@ +body { + background-color: #f1f1f1; + color: #333; + font-family: Helvetica, Arial, sans-serif; + margin: 24px; + text-shadow: white 0 1px 2px; +} + +h1, h2 { + font-weight: normal; +} + +p { + margin-left: 24px; +} + +p::first-letter { + font-weight: bold; +} diff --git a/skin/icon_128.png b/skin/icon_128.png new file mode 100755 index 0000000..da50326 Binary files /dev/null and b/skin/icon_128.png differ diff --git a/skin/icon_16.png b/skin/icon_16.png new file mode 100755 index 0000000..b14873c Binary files /dev/null and b/skin/icon_16.png differ diff --git a/skin/icon_19.png b/skin/icon_19.png new file mode 100644 index 0000000..2d9b157 Binary files /dev/null and b/skin/icon_19.png differ diff --git a/skin/icon_32.png b/skin/icon_32.png new file mode 100755 index 0000000..e005cf8 Binary files /dev/null and b/skin/icon_32.png differ diff --git a/skin/icon_48.png b/skin/icon_48.png new file mode 100755 index 0000000..971f8a5 Binary files /dev/null and b/skin/icon_48.png differ diff --git a/skin/infobar.css b/skin/infobar.css new file mode 100644 index 0000000..0156e20 --- /dev/null +++ b/skin/infobar.css @@ -0,0 +1,7 @@ +body { + cursor: default; + font-family: 'Lucida Grande', 'Lucida Sans Unicode', sans-serif; + font-size: 0.8em; + margin-top: 5px; + -webkit-user-select: none; +} diff --git a/skin/launcher.css b/skin/launcher.css new file mode 100755 index 0000000..0f89c3d --- /dev/null +++ b/skin/launcher.css @@ -0,0 +1,166 @@ +html { + cursor: default; + height: 100%; + -webkit-user-select: none; +} + +body { + background-attachment: fixed; + background-position: center; + background-size: cover; + font: 10pt normal 'Lucida Grande', 'Lucida Sans Unicode', sans-serif; + margin: 0; + padding: 4%; +} + +#infobar { + background: -webkit-linear-gradient(#ddd, #bbb); + -webkit-box-shadow: 0 0 10px #444; + left: 0; + padding: 1em 16px; + position: fixed; + top: 0; + width: 100%; +} + +a { + outline: none; +} + +.icon { + border-radius: 10px; + float: left; + margin: 3%; + padding: 2%; + text-decoration: none; + -webkit-transition-duration: 150ms, 250ms; + -webkit-transition-property: background, opacity; + -webkit-transition-timing-function: linear; + -webkit-user-drag: element; + width: 10%; +} + +.icon:hover, .icon:focus, .icon.hover { + background: rgba(0, 0, 0, 0.35); +} + +.icon * { + cursor: pointer; +} + +.icon > img { + display: block; + height: auto; + margin: 0 auto; + width: 75%; +} + +.icon > label { + color: #fff; + display: block; + line-height: 2em; + margin: 0 -10px; + overflow: hidden; + padding: 0 10px; + text-align: center; + text-overflow: ellipsis; + text-shadow: #333 0 0 10px, #333 0 0 10px; + white-space: nowrap; +} + +.icon.drag { + border-radius: 13px; + font-size: 1.3em; + position: absolute; + width: 13%; +} + +#context-menu { + background: -webkit-linear-gradient(rgba(72, 72, 72, 0.9),rgba(0, 0, 0, 0.9)); + border-radius: 10px; + color: #fff; + display: none; + list-style-type: none; + margin: 0; + max-width: 250px; + padding: 10px 0; + position: absolute; +} + +/* CSS arrow hack: + * Hypotenuse border set to color, leg borders set to transparent. Creates a + * right isoceles triangle. + */ +#context-menu > #arrow { + height: 0; + position: absolute; + width: 0; +} + +#context-menu > #arrow.top { + border-bottom: 12px solid rgba(72, 72, 72, 0.9); + border-left: 12px solid transparent; + border-right: 12px solid transparent; + top: -12px; +} + +#context-menu > #arrow.bottom { + border-top: 12px solid rgba(0, 0, 0, 0.9); + border-left: 12px solid transparent; + border-right: 12px solid transparent; + bottom: -12px; +} + +#context-menu > #arrow.left { + border-bottom: 12px solid transparent; + border-right: 12px solid rgba(59, 59, 59, 0.9); + border-top: 12px solid transparent; + left: -12px; +} + +#context-menu > #arrow.right { + border-bottom: 12px solid transparent; + border-left: 12px solid rgba(59, 59, 59, 0.9); + border-top: 12px solid transparent; + right: -12px; +} +/*(end CSS arrow hack)*/ + +#context-menu li { + margin: 0; + white-space: nowrap; +} + +#context-menu li:not(.disabled):hover > a, +#context-menu li:not(.disabled) > a:focus { + background: rgba(255, 255, 255, 0.35); +} + +#context-menu li.disabled { + color: rgba(255, 255, 255, 0.25); +} + +#context-menu li.disabled:hover > a { + background: none; +} + +#context-menu hr { + border-bottom: 1px solid rgba(255, 255, 255, 0.2); + border-top: 1px solid rgba(0, 0, 0, 0.4); + border-width: 1px 0; + height: 0; + margin: 10px 0; +} + +#context-menu a, #context-menu a:hover, #context-menu a:active { + color: inherit; + display: block; + overflow: hidden; + padding: 10px 16px; + text-decoration: none; + text-overflow: ellipsis; +} + +footer { + clear: both; +} diff --git a/skin/loading.gif b/skin/loading.gif new file mode 100755 index 0000000..9b577e1 Binary files /dev/null and b/skin/loading.gif differ diff --git a/skin/popup.css b/skin/popup.css new file mode 100644 index 0000000..535bc3a --- /dev/null +++ b/skin/popup.css @@ -0,0 +1,32 @@ +body { + cursor: default; + font-family: sans-serif; + font-size: 1em; + margin: 8px; + min-width: 300px; + -webkit-user-select: none; +} + +h3 { + font-size: 1em; + font-weight: bold; + margin: .5em 0; +} + +input[type='text'] { + width: 240px; +} + +#buttons { + float: right; +} + +#icon { + height: 48px; + vertical-align: middle; + width: 48px; +} + +canvas { + display: none; +} diff --git a/skin/prefs/IDR_CLOSE_BAR.png b/skin/prefs/IDR_CLOSE_BAR.png new file mode 100755 index 0000000..1103dac Binary files /dev/null and b/skin/prefs/IDR_CLOSE_BAR.png differ diff --git a/skin/prefs/IDR_CLOSE_BAR_H.png b/skin/prefs/IDR_CLOSE_BAR_H.png new file mode 100755 index 0000000..f5c0a5e Binary files /dev/null and b/skin/prefs/IDR_CLOSE_BAR_H.png differ diff --git a/skin/prefs/IDR_CLOSE_BAR_P.png b/skin/prefs/IDR_CLOSE_BAR_P.png new file mode 100755 index 0000000..6711f9d Binary files /dev/null and b/skin/prefs/IDR_CLOSE_BAR_P.png differ diff --git a/skin/prefs/IDR_MANAGED.png b/skin/prefs/IDR_MANAGED.png new file mode 100755 index 0000000..99f5017 Binary files /dev/null and b/skin/prefs/IDR_MANAGED.png differ diff --git a/skin/prefs/IDR_WARNING.png b/skin/prefs/IDR_WARNING.png new file mode 100755 index 0000000..8873886 Binary files /dev/null and b/skin/prefs/IDR_WARNING.png differ diff --git a/skin/prefs/button.css b/skin/prefs/button.css new file mode 100755 index 0000000..12063f3 --- /dev/null +++ b/skin/prefs/button.css @@ -0,0 +1,96 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +button:not(.custom-appearance), +input[type='button']:not(.custom-appearance), +input[type='submit']:not(.custom-appearance) { + -webkit-border-radius: 3px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -webkit-user-select: none; + background: -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5); + border: 1px solid #aaa; + color: #444; + font-size: inherit; + margin-bottom: 0; + min-width: 4em; + padding: 3px 12px; +} + +button:not(.custom-appearance):hover, +input[type='button']:not(.custom-appearance):hover, +input[type='submit']:not(.custom-appearance):hover { + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + background: #ebebeb -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9); + border-color: #999; + color: #222; +} + +button:not(.custom-appearance):active, +input[type='button']:not(.custom-appearance):active, +input[type='submit']:not(.custom-appearance):active { + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); + background: #ebebeb -webkit-linear-gradient(#f4f4f4, #efefef 40%, #dcdcdc); + color: #333; +} + +button[disabled]:not(.custom-appearance), +input[type='button'][disabled]:not(.custom-appearance), +input[type='submit'][disabled]:not(.custom-appearance), +button[disabled]:not(.custom-appearance):hover, +input[type='button'][disabled]:not(.custom-appearance):hover, +input[type='submit'][disabled]:not(.custom-appearance):hover { + -webkit-box-shadow: none; + background: -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5); + border-color: #aaa; + color: #888; +} + +button:not(.custom-appearance):focus, +input[type='submit']:not(.custom-appearance):focus, +input[type='text']:not(.custom-appearance):focus, +select:not(.custom-appearance):focus { + -webkit-box-shadow: inset 0 1px 2px white, + 0 1px 2px rgba(0, 0, 0, .2), + 0 0 1px #c0c0c0, + 0 0 1px #c0c0c0, + 0 0 1px #c0c0c0; + -webkit-transition: border-color 200ms; + /* We use border color because it follows the border radius (unlike outline). + * This is particularly noticeable on mac. */ + border-color: rgb(64, 128, 250); + outline: none; +} + +/* Search boxes use an outline because it follows the contours of the box. */ +input[type='search']:not(.custom-appearance):focus { + outline-color: rgb(64, 128, 250); +} + +/* TODO(jhawkins): Refactor button styling and remove !important here. This is + * currently necessary because individual page button element selectors have + * higher specificity. + */ +.link-button, +.link-button:focus { + -webkit-box-shadow: none !important; + background: transparent none !important; + border: none !important; + color: rgb(17, 85, 204) !important; + cursor: pointer; + /* Input elements have -webkit-small-control which overrides the body font. + * Resolve this by using 'inherit'. */ + font-family: inherit; + margin: 0; + padding: 0 4px !important; +} + +.link-button:hover { + text-decoration: underline; +} + +.link-button:active { + color: rgb(5, 37, 119) !important; + text-decoration: underline; +} diff --git a/skin/prefs/checkbox.css b/skin/prefs/checkbox.css new file mode 100755 index 0000000..ffbbfc0 --- /dev/null +++ b/skin/prefs/checkbox.css @@ -0,0 +1,169 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +input[type='checkbox'] { + -webkit-box-shadow: inset 0 1px 2px white, + 0 1px 2px rgba(0, 0, 0, .2); + -webkit-appearance: none; + -webkit-margin-start: 0; + -webkit-margin-end: 3px; + background: -webkit-linear-gradient(#fafafa, #dcdcdc); + border-radius: 3px; + border: 1px solid #a0a0a0; + display: inline-block; + height: 16px; + margin-bottom: 0; + margin-top: 0; + position: relative; + top: 3px; + vertical-align: baseline; + width: 16px; +} + +input[type='checkbox']:disabled { + opacity: .75; +} + +input[type='checkbox']:not(:disabled):not(:active):hover { + background: -webkit-linear-gradient(#fff, #e6e6e6); + text-shadow: 0 1px 0 rgba(255, 255, 255, 1); +} + +input[type='checkbox']:not(:disabled):active { + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2); + background: -webkit-linear-gradient(#f0f0f0, #bebebe); + border: 1px solid #808080; + text-shadow: 0 1px 0 rgba(255, 255, 255, .25); +} + +input[type='checkbox']:checked::before { + color: #808080; + content: url('checkmark.png'); + font-size: 13px; /* Explicitly set the font size so that the positioning + of the checkmark is correct. */ + height: 16px; + left: 2px; + position: absolute; +} + +input[type='radio'] { + -webkit-box-shadow: inset 0 1px 2px white, + 0 1px 2px rgba(0, 0, 0, .2); + -webkit-appearance: none; + -webkit-margin-start: 0; + -webkit-margin-end: 3px; + -webkit-transition: border 500ms; + background: -webkit-linear-gradient(#fafafa, #dcdcdc); + border-radius: 100%; + border: 1px solid #a0a0a0; + display: inline-block; + height: 15px; + margin-bottom: 0; + position: relative; + top: 3px; + vertical-align: baseline; + width: 15px; +} + +input[type='radio']:disabled { + opacity: .75; +} + +input[type='radio']:not(:disabled):not(:active):hover { + background: -webkit-linear-gradient(#fff, #e6e6e6); + text-shadow: 0 1px 0 rgba(255, 255, 255, 1); +} + +input[type='radio']:not(:disabled):active { + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2); + background: -webkit-linear-gradient(#f0f0f0, #bebebe); + border: 1px solid #808080; + text-shadow: 0 1px 0 rgba(255, 255, 255, .25); +} + +input[type='radio']:checked::before { + -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, .5); + -webkit-margin-start: 4px; + background: #808080; + border-radius: 10px; + content: ''; + display: inline-block; + font-size: 13px; + font-weight: 400; + height: 5px; + left: 0; + margin-top: 4px; + opacity: 1; + position: absolute; + top: 0; + vertical-align: top; + width: 5px; +} + +html[dir='rtl'] input[type='radio']:checked::before { + right: 0; +} + +input[type='radio']:active:checked::before { + background: #606060; +} + +/* .checkbox and .radio classes wrap labels. */ + +.checkbox, +.radio { + margin: 9px 0; +} + +.checkbox label, +.radio label { + display: -webkit-box; +} + +/* Make sure long spans wrap at the same place they start. */ +.checkbox label input ~ span, +.radio label input ~ span { + -webkit-box-flex: 1; + -webkit-margin-start: 0.4em; + display: block; +} + +.checkbox label input[type=checkbox], +.radio label input[type=radio] { + margin-top: 0; + top: 0; + vertical-align: top; +} + +/* These rules are copied from button.css */ +input[type='checkbox']:not(.custom-appearance):focus, +input[type='radio']:not(.custom-appearance):focus { + -webkit-box-shadow: inset 0 1px 2px white, + 0 1px 2px rgba(0, 0, 0, .2), + 0 0 1px #c0c0c0, + 0 0 1px #c0c0c0, + 0 0 1px #c0c0c0; + -webkit-transition: border-color 200ms; + border-color: #4080fa; + outline: none; +} + +label > input[type=radio] ~ span, +label > input[type=checkbox] ~ span, +input[type=checkbox] ~ label { + color: #444; +} + +label:hover > input[type=checkbox]:disabled ~ span, +label:hover > input[type=radio]:disabled ~ span, +input[type=checkbox]:disabled ~ label:hover { + color: #888; +} + +label:hover > input[type=checkbox]:not(:disabled) ~ span, +label:hover > input[type=radio]:not(:disabled) ~ span, +input[type=checkbox]:not(:disabled) ~ label:hover { + color: #222; +} diff --git a/skin/prefs/checkmark.png b/skin/prefs/checkmark.png new file mode 100755 index 0000000..00a394b Binary files /dev/null and b/skin/prefs/checkmark.png differ diff --git a/skin/prefs/chrome_shared.css b/skin/prefs/chrome_shared.css new file mode 100755 index 0000000..77ab142 --- /dev/null +++ b/skin/prefs/chrome_shared.css @@ -0,0 +1,200 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Styles common to WebUI pages that share the options pages style */ +body { + cursor: default; + font-size: 13px; +} + +a:link { + color: rgb(63, 110, 194); +} + +a:active { + color: rgb(37, 64, 113); +} + +#navbar-content-title { + -webkit-padding-end: 24px; + -webkit-user-select: none; + color: #333; + cursor: pointer; + font-size: 200%; + font-weight: normal; + margin: 0; + padding-bottom: 14px; + padding-top: 13px; + text-align: end; + text-shadow: white 0 1px 2px; +} + +#main-content { + display: -webkit-box; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; +} + +#navbar { + margin: 0; +} + +#navbar-container { + -webkit-border-end: 1px solid #c6c9ce; + background-color: #f1f1f1; + position: fixed; + bottom: 0; + /* We set both left and right for the sake of RTL. */ + left: 0; + right: 0; + top: 0; + width: 216px; + z-index: 2; +} + +html.hide-menu #navbar-container { + display: none; +} + +#navbar-container > ul { + -webkit-user-select: none; + list-style-type: none; + margin: 0; + padding: 0; +} + +.navbar-item { + border-bottom: 1px solid transparent; + border-top: 1px solid transparent; + color: #333; + cursor: pointer; + display: block; + font-size: 105%; + outline: none; + padding: 7px 0; + text-align: end; + text-shadow: white 0 1px 1px; + -webkit-padding-end: 24px; +} + +.navbar-item:focus { + border-bottom: 1px solid #8faad9; + border-top: 1px solid #8faad9; +} + +.navbar-item-selected { + -webkit-box-shadow: 0 1px 0 #f7f7f7; + background-color: #bbcee9; + border-bottom: 1px solid #8faad9; + border-top: 1px solid #8faad9; + color: black; + text-shadow: #bbcee9 0 1px 1px; +} + +#mainview { + -webkit-box-align: stretch; + -webkit-padding-start: 216px; + margin: 0; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 1; +} + +html.hide-menu #mainview { + -webkit-padding-start: 0; +} + +#mainview-content { + min-height: 100%; + position: relative; +} + +#page-container { + box-sizing: border-box; + max-width: 888px; + min-width: 600px; + padding: 0 24px; +} + +div.disabled { + color: #888; +} + +/* TEXT */ +input[type='password'], +input[type='text'], +input[type='url'], +input:not([type]) { + -webkit-border-radius: 2px; + border: 1px solid #aaa; + font-size: inherit; + padding: 3px; +} + +input[type='text']:disabled { + color: #888; +} + +/* Elements that need to be LTR even in an RTL context, but should align + * right. (Namely, URLs, search engine names, etc.) + */ +html[dir='rtl'] .weakrtl { + direction: ltr; + text-align: right; +} + +/* Input fields in search engine table need to be weak-rtl. Since those input + * fields are generated for all cr.ListItem elements (and we only want weakrtl + * on some), the class needs to be on the enclosing div. + */ +html[dir='rtl'] div.weakrtl input { + direction: ltr; + text-align: right; +} + +html[dir='rtl'] .favicon-cell.weakrtl { + -webkit-padding-end: 22px; + -webkit-padding-start: 0; +} + +/* weakrtl for selection drop downs needs to account for the fact that + * Webkit does not honor the text-align attribute for the select element. + * (See Webkit bug #40216) + */ +html[dir='rtl'] select.weakrtl { + direction: rtl; +} + +html[dir='rtl'] select.weakrtl option { + direction: ltr; +} + +/* WebKit does not honor alignment for text specified via placeholder attrib. + * This CSS is a workaround. Please remove once WebKit bug is fixed. + * https://bugs.webkit.org/show_bug.cgi?id=63367 + */ +html[dir='rtl'] input.weakrtl::-webkit-input-placeholder, +html[dir='rtl'] .weakrtl input::-webkit-input-placeholder { + direction: rtl; +} + +.page h1 { + -webkit-padding-end: 24px; + -webkit-user-select: none; + border-bottom: 1px solid #eeeeee; + color: #333; + font-size: 200%; + font-weight: normal; + margin: 0; + padding-bottom: 4px; + padding-top: 13px; + text-shadow: white 0 1px 2px; +} diff --git a/skin/prefs/chrome_shared2.css b/skin/prefs/chrome_shared2.css new file mode 100755 index 0000000..7d648d3 --- /dev/null +++ b/skin/prefs/chrome_shared2.css @@ -0,0 +1,105 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* This file holds CSS that should be shared, in theory, by all user-visible + * chrome:// pages. This contrasts chrome_shared.css, which it is meant to + * replace, but has CSS specific to options and options-like pages. */ + +@import url("chrome://resources/css/widgets.css"); + + +/* Prevent CSS from overriding the hidden property. */ +[hidden] { + display: none !important; +} + +html.loading * { + -webkit-transition-delay: 0 !important; + -webkit-transition-duration: 0 !important; +} + +body { + cursor: default; + margin: 0; +} + +p { + line-height: 1.8em; +} + +h1, +h2, +h3 { + -webkit-user-select: none; + font-weight: normal; + /* Makes the vertical size of the text the same for all fonts. */ + line-height: 1; +} + +h1 { + font-size: 1.5em; +} + +h2 { + font-size: 1.3em; + margin-bottom: 0.4em; +} + +h3 { + color: black; + font-size: 1.2em; + margin-bottom: 0.5em; +} + +a { + color: rgb(17, 85, 204); + text-decoration: underline; +} + +a:active { + color: rgb(5, 37, 119); +} + +/* Elements that need to be LTR even in an RTL context, but should align + * right. (Namely, URLs, search engine names, etc.) + */ +html[dir='rtl'] .weakrtl { + direction: ltr; + text-align: right; +} + +/* Input fields in search engine table need to be weak-rtl. Since those input + * fields are generated for all cr.ListItem elements (and we only want weakrtl + * on some), the class needs to be on the enclosing div. + */ +html[dir='rtl'] div.weakrtl input { + direction: ltr; + text-align: right; +} + +html[dir='rtl'] .favicon-cell.weakrtl { + -webkit-padding-end: 22px; + -webkit-padding-start: 0; +} + +/* weakrtl for selection drop downs needs to account for the fact that + * Webkit does not honor the text-align attribute for the select element. + * (See Webkit bug #40216) + */ +html[dir='rtl'] select.weakrtl { + direction: rtl; +} + +html[dir='rtl'] select.weakrtl option { + direction: ltr; +} + +/* WebKit does not honor alignment for text specified via placeholder attribute. + * This CSS is a workaround. Please remove once WebKit bug is fixed. + * https://bugs.webkit.org/show_bug.cgi?id=63367 + */ +html[dir='rtl'] input.weakrtl::-webkit-input-placeholder, +html[dir='rtl'] .weakrtl input::-webkit-input-placeholder { + direction: rtl; +} diff --git a/skin/prefs/disabled_select.png b/skin/prefs/disabled_select.png new file mode 100755 index 0000000..2d4de3f Binary files /dev/null and b/skin/prefs/disabled_select.png differ diff --git a/skin/prefs/list.css b/skin/prefs/list.css new file mode 100755 index 0000000..39d836a --- /dev/null +++ b/skin/prefs/list.css @@ -0,0 +1,94 @@ + +list, +grid { + display: block; + outline: none; + overflow: auto; + position: relative; /* Make sure that item offsets are relative to the + list. */ +} + +list > *, +grid > * { + -webkit-user-select: none; + background-color: rgba(255, 255, 255, 0); + border: 1px solid rgba(255, 255, 255, 0); /* transparent white */ + border-radius: 2px; + cursor: default; + line-height: 20px; + margin: -1px 0; + overflow: hidden; + padding: 0 3px; + position: relative; /* to allow overlap */ + text-overflow: ellipsis; + /*white-space: pre;*/ +} + +list > * { + display: block; +} + +grid > * { + display: inline-block; +} + +list > [lead], +grid > [lead] { + border-color: transparent; +} + +list:focus > [lead], +grid:focus > [lead] { + border-color: hsl(214, 91%, 65%); + z-index: 2; +} + +list > [anchor], +grid > [anchor] { + +} + +list:not([disabled]) > :hover, +grid:not([disabled]) > :hover { + border-color: hsl(214, 91%, 85%); + z-index: 1; + background-color: hsl(214, 91%, 97%); +} + +list > [selected], +grid > [selected] { + border-color: hsl(0, 0%, 85%); + background-color: hsl(0, 0%, 90%); + z-index: 2; + background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.8), + rgba(255, 255, 255, 0)); +} + +list:focus > [selected], +grid:focus > [selected] { + background-color: hsl(214, 91%, 89%); + border-color: hsl(214, 91%, 65%); +} + +list:focus > [lead][selected], +list > [selected]:hover, +grid:focus > [lead][selected], +grid > [selected]:hover { + background-color: hsl(214, 91%, 87%); + border-color: hsl(214, 91%, 65%); +} + +list > .spacer, +grid > .spacer { + border: 0; + box-sizing: border-box; + display: block; + overflow: hidden; + visibility: hidden; + margin: 0; +} + +list > [hidden], +grid > [hidden] { + display: none; +} diff --git a/skin/prefs/page_legacy.css b/skin/prefs/page_legacy.css new file mode 100755 index 0000000..3ec05ce --- /dev/null +++ b/skin/prefs/page_legacy.css @@ -0,0 +1,81 @@ +/* Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * This code is adapted from chrome://settings + */ + +.overlay { + -webkit-box-align: center; + -webkit-box-orient: vertical; + -webkit-box-pack: center; + -webkit-transition: 0.25s opacity; + background: -webkit-radial-gradient(rgba(127, 127, 127, 0.5), + rgba(127, 127, 127, 0.5) 35%, + rgba(0, 0, 0, 0.7)); + bottom: 0; + display: -webkit-box; + left: 0; + overflow: auto; + padding: 20px; + padding-bottom: 130px; + position: fixed; + right: 0; + top: 0; + z-index: 10; +} + +.content-area { + padding: 10px 15px 5px 15px; + -webkit-user-select: text; +} + +.content-area img { + margin-right: 10px; + vertical-align: middle; + width: 72px; + -webkit-user-select: none; +} + +.action-area { + -webkit-box-align: center; + -webkit-box-orient: horizontal; + -webkit-box-pack: end; + border-top: 1px solid rgba(188, 193, 208, .5); + display: -webkit-box; + padding: 12px; +} + +.action-area-right { + display: -webkit-box; +} + +.button-strip { + -webkit-box-orient: horizontal; + display: -webkit-box; +} + +.button-strip > button { + -webkit-margin-start: 10px; + display: block; +} + +.overlay .page { + -webkit-box-shadow: 0px 5px 80px #505050; + background: white; + border: 1px solid rgb(188, 193, 208); + border-radius: 2px; + min-width: 400px; + padding: 0; + position: relative; +} + +.overlay .page h1 { + background: -webkit-linear-gradient(white, #F8F8F8); + border-bottom: 1px solid rgba(188, 193, 208, .5); + color: #53637D; + font-size: 105%; + font-weight: bold; + margin: 0; + padding: 10px 15px 8px 15px; +} diff --git a/skin/prefs/prefs.css b/skin/prefs/prefs.css new file mode 100755 index 0000000..71b3927 --- /dev/null +++ b/skin/prefs/prefs.css @@ -0,0 +1,2988 @@ +html { + font-family: Helvetica, Arial, sans-serif; +} + +.bg-thumb { + max-height: 100px; + max-width: 100px; + vertical-align: middle; +} + +#bgDefault { + background-image: -webkit-radial-gradient(center, ellipse cover, #ccc, #666); + display: inline-block; + height: 75px; + vertical-align: middle; + width: 100px; +} + +#backgrounds-grid { + max-height: 300px; + overflow: auto; +} + +#backgrounds-grid > div { + margin: 3px; + padding: 3px; +} + +.row-delete-button { + background: url(IDR_CLOSE_BAR.png); + height: 16px; + position: absolute; + right: 6px; + top: 6px; + width: 16px; +} + +.row-delete-button:hover { + background: #e4ecf7 url(IDR_CLOSE_BAR_H.png) !important; +} + +.row-delete-button:active { + background: #bbcee9 url(IDR_CLOSE_BAR_P.png) !important; +} + +#aboutInfo { + vertical-align: top; +} + +.hbox { + display: -webkit-box; + -webkit-box-orient: horizontal; +} + +.vbox { + display: -webkit-box; + -webkit-box-orient: vertical; +} + +.stretch { + -webkit-box-flex: 1; +} + +.frozen, +.subpage-sheet-container.frozen { + position: fixed; +} + +#search-field { + font-size: inherit; + margin: 0; + width: 100%; +} + +#searchPageNav { + -webkit-padding-start: 20px; +} + +/* + * Add padding to increase the touchable area of search box. Use original font + * size to avoid the width of search box exceeding the width of navbar. + */ +html[touch-optimized] #search-field { + font-size: 13px; + padding: 5px; +} +html[touch-optimized] #search-field::-webkit-search-cancel-button { + -webkit-transform: scale(1.5); +} + +/* + * For touch-optimized UI, make the radio/checkbox input boxes in + * options/preference pages easier to touch. + * TODO(rbyers): We need to solve this more generally for all web pages + * (crbug.com/99981), and perhaps temporarily for all WebUI (crbug.com/102482). + */ +html[touch-optimized] div.radio > label > span, +html[touch-optimized] div.checkbox > label > span { + -webkit-padding-start: 5px; +} + +html[touch-optimized] label > input[type=checkbox], +html[touch-optimized] label > input[type=radio] { + -webkit-transform: scale(1.4); +} + +/* + * Override the font-size rule in shared_options.css file. + * 16 px font-size proved to be more touch friendly. It increases the touchable + * area for buttons and input boxes. + */ +html[touch-optimized] body { + font-size: 16px; +} + +.overlay { + -webkit-box-align: center; + -webkit-box-orient: vertical; + -webkit-box-pack: center; + -webkit-transition: 250ms opacity; + background: -webkit-radial-gradient(rgba(127, 127, 127, 0.5), + rgba(127, 127, 127, 0.5) 35%, + rgba(0, 0, 0, 0.7)); + bottom: 0; + display: -webkit-box; + left: 0; + overflow: auto; + padding: 20px; + padding-bottom: 130px; + position: fixed; + right: 0; + top: 0; + z-index: 10; +} + +.raw-button, +.raw-button:hover, +.raw-button:active { + -webkit-box-shadow: none; + background-color: transparent; + background-repeat: no-repeat; + border: none; + min-width: 0; + padding: 1px 6px; +} + +.close-subpage { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAiElEQVR42r2RsQrDMAxEBRdl8SDcX8lQPGg1GBI6lvz/h7QyRRXV0qUULwfvwZ1tenw5PxToRPWMC52eA9+WDnlh3HFQ/xBQl86NFYJqeGflkiogrOvVlIFhqURFVho3x1moGAa3deMs+LS30CAhBN5nNxeT5hbJ1zwmji2k+aF6NENIPf/hs54f0sZFUVAMigAAAABJRU5ErkJggg=="); + height: 16px; + min-width: 0; + position: relative; + top: 16px; + width: 16px; +} + +.close-subpage:hover { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAqklEQVR4XqWRMQ6DMAxF/1Fyilyj2SmIBUG5QcTCyJA5Z8jGhlBPgRi4TmoDraVmKFJlWYrlp/g5QfwRlwEVNWVa4WzfH9jK6kCkEkBjwxOhLghheMWMELUAqqwQ4OCbnE4LJnhr5IYdqQt4DJQjhe9u4vBBmnxHHNzRFkDGjHDo0VuTAqy2vAG4NkvXXDHxbGsIGlj3e835VFNtdugma/Jk0eXq0lP//5svi4PtO01oFfYAAAAASUVORK5CYII="); +} + +.close-subpage:active { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAARElEQVQoz2P4z4AfMlBLAYMdwxkghgEwD1XBGTC0g0sDIaYJECVwFqoChBK4WegKkJWArSJZAQErCDqSKG/iCyhaRhYA9LDIbULDzlIAAAAASUVORK5CYII="); +} + +html[dir='ltr'] .close-subpage { + float: right; + right: 20px; +} + +html[dir='rtl'] .close-subpage { + float: left; + left: 20px; +} + +html.hide-menu .close-subpage { + display: none +} + +.content-area { + padding: 10px 15px 5px 15px; +} + +.action-area { + -webkit-box-align: center; + -webkit-box-orient: horizontal; + -webkit-box-pack: end; + border-top: 1px solid rgba(188, 193, 208, .5); + display: -webkit-box; + padding: 12px; +} + +html[dir='rtl'] .action-area { + left: 0; +} + +.action-area-right { + display: -webkit-box; +} + +.button-strip { + -webkit-box-orient: horizontal; + display: -webkit-box; +} + +.button-strip > button { + -webkit-margin-start: 10px; + display: block; +} + +.bottom-strip { + padding: 12px; + position: absolute; + right: 0; + bottom: 0; + border-top: none; +} + +.overlay .page { + -webkit-box-shadow: 0 5px 80px #505050; + background: white; + border: 1px solid rgb(188, 193, 208); + border-radius: 2px; + min-width: 400px; + padding: 0; + position: relative; +} + +#subpage-backdrop { + -webkit-transition: 250ms opacity; + background-color: rgba(233, 238, 242, .5); + height: 100%; + left: 216px; + right: 216px; + position: fixed; + top: 0; + width: 100%; +} + +.subpage-sheet-container { + -webkit-transition: 250ms opacity, 100ms padding-left, 100ms padding-right; + box-sizing: border-box; + min-height: 100%; + position: absolute; + /* We set both left and right for the sake of RTL. */ + left: 0; + right: 0; + top: 0; + width: 100%; +} + +#subpage-sheet-container-1 { + -webkit-padding-start: 40px; + z-index: 5; +} + +#subpage-sheet-container-2 { + -webkit-padding-start: 80px; + z-index: 10; +} + +.subpage-sheet { + -webkit-box-shadow: #666 0 2px 5px; + background-color: white; + border-left: 1px solid #b8b8b8; + box-sizing: border-box; + min-height: 100%; + width: 100%; + min-width: 651px; +} + +.subpage-sheet-contents { + box-sizing: border-box; + max-width: 900px; + min-width: 650px; + padding: 0 20px 20px 20px; + width: 95%; +} + +.managed-prefs-banner { + background: -webkit-linear-gradient(#fff2b7, #fae691 97%, #878787); + height: 31px; + width: 100%; + margin: 0; + padding: 0; + position: relative; + vertical-align: middle; + z-index: 11; +} + +.managed-prefs-banner.clickable:active { + background: -webkit-linear-gradient(#878787, #fae691 3%, #fff2b7); +} + +.managed-prefs-icon { + background-image: url("chrome://theme/IDR_WARNING"); + background-repeat: no-repeat; + background-position:center; + display: inline-block; + padding: 5px; + height: 21px; + vertical-align: middle; + width: 24px; +} + +.managed-prefs-text { + vertical-align: middle; +} + +.subpage-sheet .page h1 { + margin-bottom: 10px; +} + +.overlay .page h1 { + background: -webkit-linear-gradient(white, #F8F8F8); + border-bottom: 1px solid rgba(188, 193, 208, .5); + font-size: 105%; + font-weight: bold; + padding: 10px 15px 8px 15px; +} + +.page list { + /* Min height is a multiple of the list item height (32) */ + min-height: 192px; +} + +/** + * TODO(kevers): Standardize formatting of sections to use display tables. + * For now, we require separate specialized rules for sections that are + * formatted as table rows. + */ +section { + -webkit-box-orient: horizontal; + border-bottom: 1px solid #eeeeee; + display: -webkit-box; + margin-top: 17px; + padding-bottom: 20px; +} + +div.page section:last-child { + border-bottom: none; +} + +h3 { + font-size: 105%; + font-weight: bold; + margin: 20px 0 10px 0; +} + +section > h3 { + margin: 0; + vertical-align: middle; + width: 130px; + -webkit-padding-end: 10px; +} + +section > div:only-of-type { + -webkit-box-flex: 1; +} + +/* Don't allow edge margin on the first/last child of a section. */ +section > h3 + * > *:last-child { + margin-bottom: 0; +} +section > h3 + * > *:first-child { + margin-top: 0; +} + +.option { + margin-top: 0; +} + +/* [hidden] does display:none, but its priority is too low in some cases. */ +[hidden] { + display: none !important; +} + +.transparent { + opacity: 0; +} + +.touch-slider { + -webkit-appearance: slider-horizontal; +} + + +.settings-list, +.settings-list-empty { + border: 1px solid #d9d9d9; + border-radius: 2px; +} + +.settings-list-empty { + background-color: #f4f4f4; + box-sizing: border-box; + min-height: 125px; + padding-left: 20px; + padding-top: 20px; +} + +list > * { + -webkit-box-align: center; + -webkit-transition: 150ms background-color; + box-sizing: border-box; + border-radius: 0; + display: -webkit-box; + height: 32px; + border: none; + margin: 0; +} + +list > .spacer { + /* The above height rule should not apply to spacers. When redraw is called + on the list they will be given an explicit element height but this ensures + they have 0 height to begin with. */ + height: 0; +} + +list:not([disabled]) > :hover { + background-color: #e4ecf7; +} + +/* TODO(stuartmorgan): Once this becomes the list style for other WebUI pages + * these rules can be simplified (since they wont need to override other rules). + */ + +list:not([hasElementFocus]) > [selected], +list:not([hasElementFocus]) > [lead][selected] { + background-color: #d0d0d0; + background-image: none; +} + +list[hasElementFocus] > [selected], +list[hasElementFocus] > [lead][selected], +list:not([hasElementFocus]) > [selected]:hover, +list:not([hasElementFocus]) > [selected][lead]:hover { + background-color: #bbcee9; + background-image: none; +} + +list[hasElementFocus] > [lead], +list[hasElementFocus] > [lead][selected] { + border-top: 1px solid #7892b4; + border-bottom: 1px solid #7892b4; +} + +list[hasElementFocus] > [lead]:nth-child(2), +list[hasElementFocus] > [lead][selected]:nth-child(2) { + border-top: 1px solid transparent; +} + +list[hasElementFocus] > [lead]:nth-last-child(2), +list[hasElementFocus] > [lead][selected]:nth-last-child(2) { + border-bottom: 1px solid transparent; +} + +list[disabled] > [lead][selected], +list[disabled]:focus > [lead][selected] { + border: none; +} + +list[disabled] { + opacity: 0.6; +} + +list > .heading { + color: #666666; +} + +list > .heading:hover { + background-color: transparent; + border-color: transparent; +} + +list .deletable-item { + -webkit-box-align: center; +} + +list .deletable-item > :first-child { + -webkit-box-align: center; + -webkit-box-flex: 1; + -webkit-padding-end: 5px; + display: -webkit-box; +} + +list .close-button { + -webkit-transition: 150ms opacity; + background-color: transparent; + /* TODO(stuartmorgan): Replace with real images once they are available. */ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAiElEQVR42r2RsQrDMAxEBRdl8SDcX8lQPGg1GBI6lvz/h7QyRRXV0qUULwfvwZ1tenw5PxToRPWMC52eA9+WDnlh3HFQ/xBQl86NFYJqeGflkiogrOvVlIFhqURFVho3x1moGAa3deMs+LS30CAhBN5nNxeT5hbJ1zwmji2k+aF6NENIPf/hs54f0sZFUVAMigAAAABJRU5ErkJggg=="); + border: none; + display: block; + height: 16px; + opacity: 1; + width: 16px; +} + +list > *:not(:hover):not([lead]) .close-button, +list > *:not(:hover):not([selected]) .close-button, +list:not([hasElementFocus]) > *:not(:hover) .close-button, +list[disabled] .close-button, +list .close-button[disabled] { + opacity: 0; + pointer-events: none; +} + +list .close-button:hover { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAqklEQVR4XqWRMQ6DMAxF/1Fyilyj2SmIBUG5QcTCyJA5Z8jGhlBPgRi4TmoDraVmKFJlWYrlp/g5QfwRlwEVNWVa4WzfH9jK6kCkEkBjwxOhLghheMWMELUAqqwQ4OCbnE4LJnhr5IYdqQt4DJQjhe9u4vBBmnxHHNzRFkDGjHDo0VuTAqy2vAG4NkvXXDHxbGsIGlj3e835VFNtdugma/Jk0eXq0lP//5svi4PtO01oFfYAAAAASUVORK5CYII="); +} + +list .close-button:active { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAARElEQVQoz2P4z4AfMlBLAYMdwxkghgEwD1XBGTC0g0sDIaYJECVwFqoChBK4WegKkJWArSJZAQErCDqSKG/iCyhaRhYA9LDIbULDzlIAAAAASUVORK5CYII="); +} + +list .static-text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +list[inlineeditable] input { + box-sizing: border-box; + margin: 0; + width: 100%; +} + +list > :not([editing]) [displaymode="edit"] { + display: none; +} + +list > [editing] [displaymode="static"] { + display: none; +} + +list > [editing] input:invalid { + /* TODO(stuartmorgan): Replace with validity badge */ + background-color: pink; +} + +.option-name { + padding-right: 5px; +} + +html[dir=rtl].option-name { + padding-left: 5px; +} + +.favicon-cell { + -webkit-padding-start: 20px; + background-position: left; + background-repeat: no-repeat; +} + +input[type="url"].favicon-cell { + -webkit-padding-start: 22px; + background-position-x: 4px; +} + +/* TODO(jhawkins): Use something better than 99.3% when CSS3 background + * positioning is available. + */ +html[dir=rtl] input.favicon-cell { + background-position-x: 99.3%; +} + +list .favicon-cell { + -webkit-margin-start: 7px; + -webkit-padding-start: 26px; + display: block; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +html[dir=rtl] list .favicon-cell { + background-position: right; +} + +html[enable-background-mode=false] #background-mode-section { + display: none; +} + +/* UI Controls */ + +/* LIST */ +html:not([os=mac]) list[hasElementFocus] { + outline: 1px solid rgba(0, 128, 256, 0.5); + outline-offset: -2px; +} + +/* This matches the native list outline on Mac */ +html[os=mac] list[hasElementFocus] { + outline-color: #759ad9; + outline-offset: -1px; + outline-style: auto; + outline-width: 5px; +} + +.suboption { + -webkit-margin-start: 23px; +} + +.informational-text { + color: grey; +} + +#main-content list.autocomplete-suggestions { + background-color: white; + border: 1px solid #aaa; + border-radius: 2px; + min-height: 0; + opacity: 0.9; + position: fixed; + z-index: 3; +} + +list.autocomplete-suggestions > div { + height: auto; +} + +list.autocomplete-suggestions:not([hasElementFocus]) > [selected], +list.autocomplete-suggestions:not([hasElementFocus]) > [lead][selected] { + background-color: #bbcee9; +} + +html:not([hasFlashPlugin]) .flash-plugin-area, +/* If the Flash plug-in supports the NPP_ClearSiteData API, we don't need to + * show the link to the Flash storage settings manager: + */ +html[flashPluginSupportsClearSiteData] .flash-plugin-area, +html:not([flashPluginSupportsClearSiteData]) .clear-plugin-lso-data-enabled, +html[flashPluginSupportsClearSiteData] .clear-plugin-lso-data-disabled { + display: none; +} + + +/* Display a collection of sections as a table in order to display nicely + * in multiple locales. + */ +.displaytable { + display: table; + width: 100%; +} + +.displaytable > section { + display: table-row; +} + +/* right table column containing settable options */ +.displaytable > section > h3 + div, +.displaytable > section > h3 + table { + padding-bottom: 20px; +} + +/* Setting the padding on the header so the alignment doesn't depend on the + * contents of the right table column. */ +.displaytable > section > h3 { + padding-top: 17px; +} + +.displaytable > section > * { + display: table-cell; + vertical-align: baseline; + border-bottom: 1px solid #eeeeee; +} + +/* do not display a border after the last section in the table */ +.displaytable:not([searching='true']) > section:last-child > * { + border-bottom: none; +} + +/* Controlled setting indicator and bubble. */ +.controlled-setting-indicator { + display: inline-block; + /* Establish a containing block for absolutely positioning the bubble. */ + position: relative; + vertical-align: text-bottom; +} + +.controlled-setting-indicator[controlled-by] summary { + background-size: contain; + height: 16px; + width: 16px; +} + +.controlled-setting-indicator summary::-webkit-details-marker { + display: none; +} + +.controlled-setting-indicator[controlled-by='policy'] summary { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY_GRAY'); +} + +.controlled-setting-indicator[controlled-by='policy'] summary:hover { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY'); +} + +.controlled-setting-indicator[controlled-by='extension'] summary { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_EXTENSION_GRAY'); +} + +.controlled-setting-indicator[controlled-by='extension'] summary:hover { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_EXTENSION'); +} + +.controlled-setting-indicator[controlled-by='recommended'] summary { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_RECOMMENDED_GRAY'); +} + +.controlled-setting-indicator[controlled-by='recommended'] summary:hover { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_RECOMMENDED'); +} + +.controlled-setting-bubble { + -webkit-margin-start: -20px; + background-color: white; + border-radius: 4px; + border: 1px solid #ccc; + box-shadow: 0 2px 2px #ddd; + margin-top: 10px; + padding: 10px; + position: absolute; + top: 50%; + z-index: 10; +} + +html[dir='ltr'] .controlled-setting-bubble { + left: 50%; +} + +html[dir='rtl'] .controlled-setting-bubble { + right: 50%; +} + +.controlled-setting-bubble::before { + -webkit-margin-start: 4px; + border-color: #ccc transparent; + border-style: solid; + border-width: 0 5px 5px; + content: ''; + position: absolute; + top: -5px; +} + +.controlled-setting-bubble::after { + -webkit-margin-start: 5px; + border-color: white transparent; + border-style: solid; + border-width: 0 4px 4px; + content: ''; + position: absolute; + top: -4px; +} + +.controlled-setting-bubble-text { + -webkit-padding-start: 30px; + background-repeat: no-repeat; + margin: 0; + min-height: 32px; + min-width: 200px; +} + +.controlled-setting-indicator[controlled-by='policy'] + .controlled-setting-bubble-text { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY_LARGE'); +} + +.controlled-setting-indicator[controlled-by='extension'] + .controlled-setting-bubble-text { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_EXTENSION_LARGE'); +} + +.controlled-setting-indicator[controlled-by='recommended'] + .controlled-setting-bubble-text { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_RECOMMENDED_LARGE'); +} + +html[dir='rtl'] .controlled-setting-bubble-text { + background-position: right top; +} + +.controlled-setting-bubble-action { + padding: 0 !important; +} + +/* + * Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#advancedPage .section-group:not(:first-child) { + margin-top: 10px; +} + +#advancedPage .section-group:not(:last-child) { + margin-bottom: 10px; +} + +#advancedPage select, +#advancedPage .web-content-select-label { + min-width: 145px; +} + +#advancedPage .web-content-select-label > span:only-of-type { + display: inline-block; + min-width: 100px; +} + +#download-location-group { + margin: 10px 0 5px; + min-width: 470px; +} + +#fontSettingsCustomizeFontsButton, +#privacyClearDataButton { + margin-left: 10px; +} + +#alertOverlayMessage { + width: 400px; +} + +.autofill-list-item { + -webkit-box-flex: 1; + -webkit-padding-start: 8px; + overflow: hidden; + text-overflow: ellipsis; +} + +.autofill-list-item + img { + -webkit-padding-end: 20px; + vertical-align: middle; +} + +#autofill-options > div:last-child { + margin-top: 15px; +} + +#autofill-options > div.settings-list > div:last-child { + border-top: 1px solid #d9d9d9; + padding: 5px 10px; +} + +#autofill-add-address, +#autofill-add-creditcard { + margin: 2px 0; +} + +.autofill-list-item + button, +.autofill-list-item + img + button { + background: #8aaaed !important; /* Gets overwritten by raw-button:hover */ + color: #fff; + margin-top: 0; +} + +#address-list > div:not(:hover) * button, +#creditcard-list > div:not(:hover) * button { + display: none; +} + +#autofill-edit-address-overlay { + min-width: 510px; +} + +#autofill-edit-credit-card-overlay { + min-width: 500px; +} + +div.table { + display: table; +} + +div.cell { + display: table-cell; +} + +div.row { + display: table-row; +} + +div.input { + padding: 2px; +} + +/* Size to match large name fields. */ +#company-name, #addr-line-1, #addr-line-2 { + width: 206px; +} + +#country { + max-width: 450px; +} + +#autofill-edit-address-overlay list { + /* Min height is a multiple of the list item height (32) */ + min-height: 32px; + width: 176px; +} + +#autofill-edit-address-overlay list div.static-text { + -webkit-box-flex: 1; + -webkit-border-radius: 2px; + -webkit-padding-start: 4px; + -webkit-padding-end: 4px; + border: 1px solid darkGray; + /* Set the line-height and min-height to match the height of an input element, + * so that even empty cells renderer with the correct height. + */ + line-height: 1.75em; + min-height: 1.75em; + width: 141px; +} + +#autofill-edit-address-overlay list input { + width: 151px; +} + +#autofill-name-labels { + -webkit-box-orient: horizontal; + /* Set the margin to compensate for each list item's close button and + * padding. + */ + -webkit-margin-end: 25px; + display: -webkit-box; +} + +#autofill-name-labels label { + -webkit-box-flex: 1; + display: block; + /* Set the minimum width to the size of an input element, so that all boxes + * have an equal amount of flex space to work with. + */ + min-width: 141px; +} + +#autofill-edit-address-overlay list#full-name-list div.static-text { + width: 131px; +} + +#autofill-edit-address-overlay list#full-name-list input { + width: 141px; +} + +#autofill-edit-address-overlay list#full-name-list { + width: 100%; +} + +#full-name-list div[role="listitem"] > div { + -webkit-box-orient: horizontal; + display: -webkit-box; +} + +#full-name-list div[role="listitem"] > div > div { + -webkit-box-flex: 1; +} + +#startupPageManagement.settings-list > :last-child { + border-top: 1px solid #d9d9d9; + padding: 5px 10px; +} + +#startupPagesList { + min-height: 64px; +} + +#startupPagesList .title { + width: 40%; +} + +#startupPagesList .url { + -webkit-box-flex: 1; + color: #666; +} + +#startupPagesList > * { + max-width: 700px; +} + +#startupPagesListDropmarker { + background-clip: padding-box; + background-color: hsl(214, 91%, 65%); + border-bottom-color: transparent; + border-radius: 0; + border-top-color: transparent; + border: 2px solid hsl(214, 91%, 65%); + box-sizing: border-box; + display: none; + height: 6px; + overflow: hidden; + pointer-events: none; + position: fixed; + z-index: 10; +} + +#customHomePageGroup { + display: -webkit-box; + -webkit-box-orient: horizontal; +} + +#customHomePageGroup > :last-child { + -webkit-margin-start: 1ex; + -webkit-box-flex: 1; + position: relative; +} + +#customHomePageGroup > div.radio { + margin-top: 0; +} + +#homepageURL { + box-sizing: border-box; + margin-top: -4px; + width: 100%; +} + +#defaultSearchEngineGroup { + display: -webkit-box; + -webkit-box-orient: vertical; +} + +#defaultSearchEngineGroup > div { + display: -webkit-box; + -webkit-box-orient: horizontal; +} + +#defaultSearchEngine { + display: block; + -webkit-box-flex: 1; + max-width: 200px; +} + +#defaultSearchManageEnginesButton { + margin-top: 0; + -webkit-margin-start: 10px; +} + +#defaultBrowserState { + margin-top: 6px; +} + +#instantOption { + margin-bottom: 3px; + margin-top: 10px +} + +#instantConfirmText { + font-family: inherit; + white-space: pre-wrap; + width: 500px; +} + +#instantConfirmLearnMore { + position: absolute; + bottom: 18px; +} + +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +#clearBrowserDataOverlay { + min-width: 500px; +} + +#clearBrowserDataOverlay > .content-area label { + margin: 5px 0; +} + +#clear-data-checkboxes { + -webkit-padding-start: 8px; + margin: 5px 0; +} + +#cbdThrobber { + margin: 4px 10px; + vertical-align: middle; + visibility: hidden; +} + +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.exception-pattern { + -webkit-box-flex: 1; + -webkit-margin-end: 10px; + -webkit-margin-start: 14px; +} + +.exception-setting { + display: inline-block; + width: 120px; +} + +select.exception-setting { + vertical-align: middle; +} + +#exception-column-headers { + -webkit-margin-start: 17px; + display: -webkit-box; + margin-top: 17px; +} + +#exception-column-headers > div { + font-weight: bold; +} + +#exception-pattern-column { + -webkit-box-flex: 1; +} + +#exception-behavior-column { + width: 145px; +} + +.otr-explanation { + font-style: italic; +} + +#content-settings-exceptions-area list { + margin-bottom: 10px; + margin-top: 4px; +} + +#disable-plugins-container { + margin: 7px 0; +} + +div[role="listitem"][managedby] { + color: #666; + font-style: italic; + position: relative; +} + +.settings-list div[role="listitem"][managedby="policy"], +.settings-list div[role="listitem"][managedby="extension"] { + background: -webkit-linear-gradient(#fff1b5, #fae692); + border-top: 0; + border-bottom: 1px solid #c9bd8d; +} + +list div[role="listitem"][managedby="policy"] .close-button { + background-image: url("chrome://theme/IDR_MANAGED"); + opacity: 1; +} + +list div[role="listitem"][managedby="extension"] .close-button { + background-image: url("chrome://theme/IDR_EXTENSIONS_SECTION_SMALL"); + opacity: 1; +} + +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +/* styles for the cookies list elements in cookies_view.html */ +#remove-all-cookies-search-column { + bottom: 10px; + position: absolute; + right: 0; +} + +html[dir=rtl] #remove-all-cookies-search-column { + left: 0; + right: auto; +} + +#cookies-column-headers { + position: relative; + width: 100%; +} + +#cookies-column-headers h3 { + font-size: 105%; + font-weight: bold; + margin: 10px 0; +} + +/* notice the width and padding for these columns match up with those below */ +#cookies-site-column { + display: inline-block; + font-weight: bold; + width: 11em; +} + +#cookies-data-column { + -webkit-padding-start: 7px; + display: inline-block; + font-weight: bold; +} + +#cookies-list { + border: 1px solid #D9D9D9; + margin: 0; +} + + +/* enable animating the height of items */ +list.cookie-list .deletable-item { + -webkit-transition: height .15s ease-in-out; +} + +/* disable webkit-box display */ +list.cookie-list .deletable-item > :first-child { + display: block; +} + +/* force the X for deleting an origin to stay at the top */ +list.cookie-list > .deletable-item > .close-button { + position: absolute; + right: 2px; + top: 8px; +} + +html[dir=rtl] list.cookie-list > .deletable-item > .close-button { + left: 2px; + right: auto; +} + + +/* styles for the site (aka origin) and its summary */ +.cookie-site { + /* notice that the width, margin, and padding match up with those above */ + -webkit-margin-end: 2px; + -webkit-padding-start: 5px; + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + width: 11em; +} + +list.cookie-list > .deletable-item[selected] .cookie-site { + -webkit-user-select: text; +} + +.cookie-data { + display: inline-block; +} + +.cookie-size { + display: inline-block; + float: right; + margin-right: 3em; +} + +list.cookie-list > .deletable-item[selected] .cookie-data { + -webkit-user-select: text; +} + + +/* styles for the individual items (cookies, etc.) */ +.cookie-items { + /* notice that the margin and padding match up with those above */ + -webkit-margin-start: 11em; + -webkit-padding-start: 7px; + -webkit-transition: .15s ease-in-out; + height: 0; + opacity: 0; + /* make the cookie items wrap correctly */ + white-space: normal; +} + +.measure-items .cookie-items { + -webkit-transition: none; + height: auto; + visibility: hidden; +} + +.show-items .cookie-items { + opacity: 1; +} + +.cookie-items .cookie-item { + background: #E0E9F5; + border-radius: 5px; + border: 1px solid #8392AE; + display: inline-block; + font-size: 85%; + height: auto; + margin: 2px 4px 2px 0; + max-width: 100px; + min-width: 40px; + overflow: hidden; + padding: 0 3px; + text-align: center; + text-overflow: ellipsis; +} + +.cookie-items .cookie-item:hover { + background: #EEF3F9; + border-color: #647187; +} + +.cookie-items .cookie-item[selected] { + background: #F5F8F8; + border-color: #B2B2B2; +} + +.cookie-items .cookie-item[selected]:hover { + background: #F5F8F8; + border-color: #647187; +} + + +/* styles for the cookie details box */ +.cookie-details { + background: #F5F8F8; + border-radius: 5px; + border: 1px solid #B2B2B2; + margin-top: 2px; + padding: 5px; +} + +list.cookie-list > .deletable-item[selected] .cookie-details { + -webkit-user-select: text; +} + +.cookie-details-table { + table-layout: fixed; + width: 100%; +} + +.cookie-details-label { + vertical-align: top; + white-space: pre; + width: 10em; +} + +.cookie-details-value { + word-wrap: break-word; +} + +/* +Copyright (c) 2012 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.details-view { + -webkit-padding-end: 10px; +} + +.extension-list-item { + padding-bottom: 7px; + padding-top: 7px; + width: 100%; + -webkit-user-select: auto; +} + +/* Get rid of display: table, which causes width issues. */ +#extension-settings .displaytable { + display: block; +} +/* Get rid of display: table row, which causes width issues. */ +#extension-settings .displaytable > section { + display: block; +} +/* Get rid of display: table cell, which causes width issues. */ +#extension-settings .displaytable > section > * { + display: block; +} + +.extension-settings-content { + border-bottom : 0 solid #eee; + margin-top: 3px; +} + +#extension-settings-list { + min-height: 0; + overflow-y: hidden; +} + +/* Get rid of the light-blue background on list item hover. */ +#extension-settings-list:not([disabled]) > :hover { + background-color: white; + border-color: #CDCDCD; +} + +.butter-bar { + background: #FFF299; + padding: 2px 5px; + border-radius: 3px; + white-space: normal; +} + +.search-suppress { + display: none; + height: 0; +} + +.extension-list-item-collaped { + height: auto; + margin-bottom: 16px; + -webkit-transition: padding 300ms, overflow 300ms, opacity 700ms; +} + +.extension-list-item-expanded { + height: auto; + margin-bottom: 16px; + overflow: visible; + -webkit-transition: padding 300ms, overflow 300ms, opacity 700ms; +} + +.extension-settings { + overflow-x: hidden; +} + +.extension-icon { + height: 48px; + vertical-align: text-top; + width: 48px; + -webkit-padding-start: 15px; + -webkit-padding-end: 15px; + -webkit-user-select: none; +} + +.extension-title { + font-size: 16px; + font-weight: 500; + -webkit-padding-end: 20px; +} + +.extension-version { + font-size: 13px; + font-weight: 400; + -webkit-padding-end: 7px; +} + +.extension-description { + font-size: 13px; + white-space: normal; + -webkit-padding-end: 5px; +} + +.extension-checkbox-span { + -webkit-margin-start: 7px; +} + +.extension-checkbox-label { + -webkit-margin-end: 10px; +} + +.extension-delete { + -webkit-margin-start: 5px; +} + +.extension-details-hidden { + opacity: 0; + max-height: 0; + -webkit-transition: max-height 400ms, opacity 200ms; +} + +.extension-details-visible { + opacity: 1; + max-height: 1000px; + -webkit-transition: max-height 200ms, opacity 300ms; +} + +.extension-links-view { + -webkit-padding-start: 15px; +} + +.extension-links-trailing { + -webkit-padding-end: 7px; +} + +.extension-zippy-container { + cursor: pointer; + width: 20px; + -webkit-user-select: none; +} + +.extension-warnings-title { + color: red; +} + +.extension-warnings { + margin-top: 6px; +} + +.extension-warnings ul { + margin: 0; +} + +.extension-warnings > * { + white-space: normal; +} + +.informative-text { + color: gray; +} + +.extension-zippy-default { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAALCAYAAABcUvyWAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACsSURBVChTY3h778z/k9c+/EcHDFunB/5nYJb5f+bJdxQ5JnFpDQaGv08Y4sMDGK6++cMAA0z///8Ds68e3ckQGRLKcPbBR4jcqY1l/4EUHOs7+v+///zTfyZGuGYI4+L+jQwpM3YzMDEwoErxKFowhNrrgIyqgBvDLGP2f/6ea2DXMZzaVA6WYJc1/j977324kxkOLkkCSrD/n7TtBoo/GC7umva/Zf4lDJ8DAMX+kKcegZRQAAAAAElFTkSuQmCC"); + background-repeat: no-repeat; + background-position: center top; + position: absolute; + left: 12px; + right: 12px; + top: 25px; + width: 6px; + height: 16px; + opacity: .25; +} + +.extension-zippy-collapsed { + -webkit-transition: -webkit-transform 100ms; + -webkit-transform: rotate(0deg); +} + +html[dir="rtl"] .extension-zippy-collapsed { + -webkit-transform: rotate(180deg); +} + +.extension-zippy-collapsed:hover { + opacity: .5; + -webkit-transform: rotate(5deg); + -webkit-transition: -webkit-transform 100ms, opacity 100ms; +} + +html[dir="rtl"] .extension-zippy-collapsed:hover { + -webkit-transform: rotate(175deg); +} + +.extension-zippy-expanded { + -webkit-transition: -webkit-transform 100ms; + -webkit-transform: rotate(90deg); +} + +.extension-zippy-expanded:hover { + -webkit-transition: -webkit-transform 100ms; + -webkit-transform: rotate(85deg); +} + +html[dir="rtl"] .extension-zippy-expanded:hover { + -webkit-transform: rotate(95deg); +} + +.extension-enabling { + position: relative; + top: 3px; +} + +.extension-enabling-label { + color: black; + -webkit-padding-start: 3px; + -webkit-padding-end: 9px; +} + +.extension-enabling-label-bold { + font-weight: bold; +} + +.extension-inspect-table { + padding: 0; + border-spacing: 0; +} + +.extension-inspect-left-column { + vertical-align: text-top; +} + +/* Dev */ + +.dev-open { + border-bottom: 1px solid rgb(205, 205, 205); + height: 32px; + padding-bottom: 7px; + padding-top: 13px; + -webkit-padding-start: 4px; + -webkit-padding-end: 3px; + -webkit-transition: padding 300ms, height 300ms, opacity 700ms; +} +.dev-closed { + height: 0; + opacity: 0; + padding-top: 9px; + -webkit-padding-start: 4px; + -webkit-padding-end: 3px; + -webkit-transition: padding 300ms, height 700ms, opacity 200ms; +} + +.dev-button-visible { + display: inherit; + opacity: 1; + -webkit-transition: opacity 200ms; +} + +.dev-button-hidden { + display: none; +} + +#suggest-gallery { + -webkit-padding-start: 10px; +} + +#dev-toggle { + display: block; + text-align: end; + margin-top: -28px; + -webkit-margin-end: 8px; +} + +#get-more-extensions-container { + display: -webkit-box; +} + +#get-more-extensions { + padding-top: 5px; + font-size: 15px; + -webkit-padding-start: 10px; +} + +#dev-table tr { + white-space: nowrap; +} + +/* Support full keyboard accessibility without making things ugly + for users who click, by hiding some focus outlines when the user + clicks anywhere, but showing them when the user presses any key. */ +body.hide-some-focus-outlines .extension-zippy-container { + outline: none; +} + +#font-settings > section { + overflow: hidden; +} + +#font-settings input[type="range"] { + width: 100%; +} + +#minimum-font-sample { + height: 35px; + overflow: hidden; + width: 270px; +} + +.font-input-div { + -webkit-margin-end: 3em; + width: 12em; +} + +.font-input-div > div > select { + margin-bottom: 10px; +} + +.font-input { + width: 100%; +} + +.font-sample-div { + height: 70px; + overflow: hidden; + width: 270px; + direction: ltr; +} + +.font-settings-huge { + float: right; +} + +html[dir=rtl] .font-settings-huge { + float: left; +} + +/* + * Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +.handlers-column-headers { + display: -webkit-box; + font-size: 13px; + font-weight: bold; +} + +.handlers-type-column { + width: 100px; + -webkit-margin-end: 10px; + -webkit-margin-start: 14px; +} + +.handlers-site-column { + max-width: 180px; +} + +.handlers-site-column select { + max-width: 170px; +} + +.handlers-remove-column { + -webkit-box-flex: 1; +} + +.handlers-remove-link { + color: #555; + cursor: pointer; + opacity: 0; + padding-left: 14px; + text-decoration: underline; + -webkit-transition: 150ms opacity; +} + +div > .handlers-remove-column { + opacity: 0; +} + +div:not(.none):hover > .handlers-remove-column { + opacity: 1; +} + +#handlers { + min-height: 250px; +} + +#handler-options list { + border-radius: 2px; + border: solid 1px #D9D9D9; + margin-bottom: 10px; + margin-top: 4px; +} + +#import-from-div { + margin-bottom: 20px; +} + +#import-checkboxes > div:not(:first-child) { + -webkit-padding-start: 8px; + margin: 5px 0; +} + +#import-throbber { + margin: 4px 10px; + vertical-align: middle; + visibility: hidden; +} + +#import-success-header { + font-size: 1.2em; +} + +#import-success-image { + text-align: center; + margin: 20px; +} + + +.language-options { + display: -webkit-box; + margin: 10px 0; +} + +.language-options-lower-left button, +.language-options-right button { + min-width: 70px; +} + +.language-options h3 { + -webkit-margin-start: 12px; + font-size: 100%; + font-weight: bold; + margin-top: 12px; +} + +.language-options-contents { + -webkit-padding-start: 12px; + -webkit-padding-end: 12px; + padding-bottom: 10px; +} + +.language-options-header, .language-options-footer { + margin: 10px 0; +} + +.language-options-left, .language-options-right { + border: 1px solid #cccccc; + vertical-align: top; + padding: 0; + height: 400px; +} + +.language-options-left { + -webkit-box-orient: vertical; + display: -webkit-box; + background-color: #ebeff9; + width: 200px; +} + +/* On OS X we use the native OS spellchecker, so don't display the dictionary */ +/* pane. */ +html[os=mac] .language-options-left { + background-color: white; +} + +html[os=mac] .language-options-right { + visibility: hidden; +} + +.language-options-lower-left { + -webkit-box-flex: 0; + -webkit-padding-start: 12px; + padding-bottom: 10px; +} + +.language-options-right { + /* To share the center line with the left pane. */ + -webkit-margin-start: -1px; + width: 360px; +} + +.language-options-notification { + display: none; + background-color: #fff29e; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + padding: 12px 30px 12px 12px; +} + +#language-options-input-method-list button { + display: block; + -webkit-margin-start: 20px; +} + +#language-options-ui-language-button { + width: 95%; + -webkit-margin-start: 10px; +} + +#language-options-spell-check-language-button { + width: 95%; + -webkit-margin-start: 10px; +} + +#language-options-input-method-list label { + margin: 4px 0; +} + +#language-options-list { + -webkit-box-flex: 1; + outline: none; + padding: 1px 0 0; + width: 100%; +} + +#language-options-list .language-name { + -webkit-box-flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#language-options-list li { + -webkit-padding-start: 12px; + padding-top: 2px; + padding-bottom: 2px; +} + +#language-options-list-dropmarker { + background-color: hsl(214, 91%, 65%); + background-clip: padding-box; + border: 3px solid hsl(214, 91%, 65%); + border-bottom-color: transparent; + border-top-color: transparent; + border-radius: 0; + box-sizing: border-box; + display: none; + height: 8px; + overflow: hidden; + pointer-events: none; + position: fixed; + z-index: 10; +} + +#language-options-ui-restart-button { + margin-top: 12px; +} + +/* + * In ChromeOS we present the language choices as a big page of links. + */ + +html[os=chromeos] #add-language-overlay-language-list { + -webkit-column-count: 2; + -webkit-column-gap: 20px; +} + +html[os=chromeos] #add-language-overlay-cancel-button { + /* Place the button in the center. */ + display: block; + margin: auto; + margin-top: 15px; +} + +html[os=chromeos] #add-language-overlay-page { + width: 800px; + padding: 20px; +} + +html[os=chromeos] #add-language-overlay-page button.link-button { + padding: 0; + text-align: left; +} + +html[os=chromeos] #add-language-overlay-page ul { + padding: 0; + margin: 0; +} + +/* TODO(kochi): This is temporary copy from new_tab.css */ +/* Notification */ + +#notification { + position: relative; + background-color: hsl(52, 100%, 80%); + border: 1px solid rgb(211, 211, 211); + border-radius: 6px; + padding: 7px 15px; + white-space: nowrap; + display: table; + /* Set the height and margin so that the element does not use any vertical + space */ + height: 16px; + margin: -44px auto 12px auto; + font-weight: bold; + opacity: 0; + pointer-events: none; + -webkit-transition: opacity 150ms; + z-index: 1; + color: black; +} + +#notification > * { + display: table-cell; + max-width: 500px; + overflow: hidden; + text-overflow: ellipsis; +} + +#notification.show { + opacity: 1; + pointer-events: all; + -webkit-transition: opacity 1s; +} + +#notification .link { + cursor: pointer; + text-decoration: underline; + -webkit-appearance: none; + border: 0; + background: none; + color: rgba(0, 102, 204, 0.3); + -webkit-padding-start: 20px; +} + +#notification .link-color { + color: rgb(0, 102, 204); +} + +#chewing-max-chi-symbol-len { + width: 100px; + height: 30%; +} + +#add-language-overlay-page .content-area { + padding-bottom: 10px; +} + +.text-button, +.text-button:active, +.text-button:focus, +.text-button:hover { + -webkit-box-shadow: none; + background: transparent none; + border-color: transparent; + color: #000; +} + +button[disabled].text-button, +button[disabled].text-button:active, +button[disabled].text-button:focus, +button[disabled].text-button:hover { + -webkit-box-shadow: none; + background: transparent none; + border-color: transparent; + color: #AAA; +} + +/* Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#manage-profile-overlay { + width: 500px; +} + +.profile-icon-grid-item { + border: none !important; + height: 31px; + margin: 4px 6px; + padding: 4px; + width: 38px; +} + +.profile-icon { + height: 31px; + width: 38px; +} + +#manage-profile-content > :first-child { + margin-bottom: 5px; +} + +#manage-profile-content > :last-child { + margin-top: 5px; +} + +#manage-profile-content > :not(:first-child):not(:last-child) { + margin-top: 5px; + margin-bottom: 5px; +} + +#manage-profile-name-div { + -webkit-box-align: baseline; + -webkit-box-orient: horizontal; + display: -webkit-box; +} + +#manage-profile-name-label { + -webkit-margin-end: 20px; +} + +#manage-profile-name { + -webkit-box-flex: 1; + display: block; +} + +#manage-profile-name:invalid { + background-color: pink; +} + +#manage-profile-error-bubble { + -webkit-transition: max-height 200ms, padding 200ms; + background-color: #eeb939; + border-radius: 4px; + font-weight: bold; + margin-left: auto; + margin-right: auto; + max-height: 50px; + overflow: hidden; + padding: 1px 10px; + text-align: center; + width: 80%; +} + +#manage-profile-error-bubble[hidden] { + display: block !important; + max-height: 0; + padding: 0 10px; +} + +#manage-profile-icon-grid { + background-color: rgba(255, 255, 255, 0.75); + border: 1px solid rgba(0, 0, 0, 0.3); + padding: 2px; +} + +#delete-profile-message { + background-repeat: no-repeat; + -webkit-padding-start: 48px; +} + +html[dir='rtl'] #delete-profile-message { + background-position: right; +} +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.packExtensionHeading { + width: 520px; + padding-bottom: 5px; +} + +.packExtensionTextBoxes { + text-align: right; +} + +.packExtensionTextArea { + width: 260px; +} + +/* + * Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#password-search-column { + bottom: 10px; + position: absolute; + right: 0; +} + +html[dir=rtl] #password-search-column { + left: 0; + right: auto; +} + +#password-list-headers { + position: relative; + width: 100%; +} + +#password-list-headers h3 { + font-size: 105%; + font-weight: bold; + margin: 10px 0; +} + +#passwords-title { + display: inline-block; +} + +/* + * Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +button.password-button { + -webkit-transition: opacity .15s; + background: #8aaaed; + color: #fff; + display: inline; + font-size: 90%; + font-weight: bold; + height: 18px; + opacity: 0.3; + padding: 0 2px; + position: absolute; + top: 5px; +} + +button.password-button:hover { + -webkit-transition: opacity .15s; + opacity: 1; +} + +html[dir='ltr'] button.password-button { + right: 2px; +} + +html[dir='rtl'] button.password-button { + left: 2px; +} + +input[type="password"].inactive-password { + background: transparent; + border: none; +} + +#saved-passwords-list .url { + box-sizing: border-box; + width: 40%; +} + +#saved-passwords-list .name { + -webkit-box-flex: 1; + width: 20%; +} + +#saved-passwords-list .password { + -webkit-box-flex: 1; + position: relative; +} + +#saved-passwords-list .password input[type="password"], +#saved-passwords-list .password input[type="text"] { + box-sizing: border-box; + width: 100%; +} + +#password-exceptions-list .url { + -webkit-box-flex: 1; +} + +#saved-passwords-list .url, +#saved-passwords-list .name, +#password-exceptions-list .url { + overflow: hidden; + text-overflow: ellipsis; +} + +#account-picture-wrapper { + border-radius: 4px; + border: 1px solid rgba(0, 0, 0, 0.3); + display: inline-block; + margin: 5px 10px 5px 2px; + padding: 3px; +} + +#account-picture { + width: 70px; + height: 70px; + vertical-align: middle; +} + +#sync-buttons, #profiles-buttons { + margin-top: 10px; +} + +#start-stop-sync { + margin-left: 0; + margin-right: 5px; +} + +#profiles-list { + min-height: 0; + margin-bottom: 10px; +} + +#profiles-list > * { + height: 40px; +} + +.profile-img { + height: 31px; + padding: 3px; + vertical-align: middle; + width: 38px; +} + +.profile-item-current { + font-weight: bold; +} + +#themes-gallery-div { + margin: 10px 0; +} + +.sync-error { + background: #FFDBDB; + border: 1px solid #ce4c4c; + border-radius: 2px; + padding: 10px; +} + +.sync-error .link-button { + margin: 0 1ex; + padding: 0; +} + +#enable-auto-login-checkbox { + margin-top: 10px; +} + +#mac-passwords-warning { + margin-top: 10px; +} + +.search-engine-list > div { + display: -webkit-box; +} + +.search-engine-list .favicon { + padding: 1px 7px 0 7px; + height: 16px; +} + +.search-engine-list .name-column { + -webkit-box-align: center; + -webkit-padding-end: 1ex; + box-sizing: border-box; + display: -webkit-box; + width: 37%; +} + +.search-engine-list .name-column :last-child { + -webkit-box-flex: 1; +} + +.search-engine-list .keyword-column { + -webkit-padding-end: 1ex; + box-sizing: border-box; + width: 26%; +} + +.search-engine-list .url-column { + box-sizing: border-box; + width: 37%; +} + +.search-engine-list .keyword-column, +.search-engine-list .url-column { + color: #666666; +} + +.search-engine-list .default .name-column, +.search-engine-list .default .keyword-column { + font-weight: bold; +} + +/* For temporary Make Default button */ +.search-engine-list .url-column { + display: -webkit-box; + -webkit-box-align: center; +} + +.search-engine-list .url-column :first-child { + -webkit-box-flex: 1; +} + +.search-engine-list .url-column button { + -webkit-margin-start: 3px; + background: #8aaaed; + color: #fff; + margin-top: 0; +} + +.search-engine-list > :not(:hover):not([editing]) .url-column button { + display: none; +} + +/* End temporary Make Default button styling */ + +.search-hidden { + display: none !important; +} + +.search-highlighted { + background-color: rgba(255, 240, 120, 0.9); +} + +.search-bubble { + -webkit-box-shadow: 0 2px 2px #888; + background-color: rgba(255, 240, 120, 0.8); + border-radius: 6px; + box-shadow: 0 2px 2px #888; + left: 0; + margin: 12px 0 0; + padding: 4px 10px; + pointer-events: none; + position: absolute; + text-align: center; + top: -1000px; /* minor hack: position off-screen by default */ + width: 100px; +} + +.search-bubble:after { + border-color: rgba(255, 240, 120, 0.9) transparent; + border-style: solid; + border-width: 0 10px 10px; + content: ""; + left: 50px; + position: absolute; + top: -10px; +} + +.search-bubble-wrapper { + position: relative; +} + +/* +Copyright (c) 2010 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.subpages-nav-tabs .tab { + position: relative; + padding: 4px 8px; +} + +.subpages-nav-tabs .active-tab { + position: relative; + background: white; + border: 1px solid #A0A0A0; /* light gray */ + border-bottom: 2px solid white; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +/* To avoid tabs changing size when they are clicked and their labels become + * bold, we actually put two labels inside each tab: an inactive label and an + * active label. Only one is visible at a time, but the bold label is used to + * size the tab even when it's not visible. This keeps the tab size constant. + */ +.subpages-nav-tabs .active-tab-label { + font-weight: bold; +} + +.subpages-nav-tabs .tab-label { + position: absolute; + top: 5px; + left: 9px; +} + +html[dir=rtl] .subpages-nav-tabs .tab-label { + right: 9px; +} + +.subpages-nav-tabs .active-tab-label, +.subpages-nav-tabs .active-tab .tab-label { + visibility: hidden; +} + +/* .tab is not removed when .active-tab is added, so we must + * override the hidden visibility above in the active tab case. + */ +.subpages-nav-tabs .active-tab .active-tab-label { + visibility: visible; +} + +.subpages-nav-tabs { + padding: 4px; + border-bottom: 1px solid #A0A0A0; /* light gray */ + background: -webkit-linear-gradient(white, #F3F3F3); /* very light gray */ + margin-bottom: 15px; +} + +.subpages-tab-contents { + display: none; + -webkit-padding-start: 10px; +} + +.active-tab-contents { + display: block; +} + +/* TODO(jhawkins): Organize these by page. */ + +#sync-setup-overlay * h4 { + margin: 5px 0; +} + +#sync-setup-overlay * form { + -webkit-user-select: none; +} + +#sync-setup-overlay * .content-area { + padding: 10px 15px; +} + +.action-area-link-container { + -webkit-box-flex: 1; +} + +.sync-customize-section-container { + margin: 5px 0 10px 0; +} + +#sync-custom-passphrase { + margin: 0 25px; +} + +#sync-passphrase-message { + color: gray; +} + +.sync-custom-passphrase-input { + margin: 10px 0; +} + +#sync-existing-passphrase-container { + background: #fff29e; + border: 1px solid #d4cdad; + padding: 10px; +} + +#sync-select-container { + margin-bottom: 10px; +} + +#sync-instructions-container { + margin-bottom: 30px; +} + +#choose-data-types-body { + margin: 10px 0; +} + +#choose-data-types-body > div { + -webkit-column-count: 3; +} + +#sync-setup-overlay { + -webkit-user-select: none; + background-color: #fff; + margin-bottom: 6px; + margin-top: 6px; + width: 500px; +} + +#sync-setup-overlay * a:link { + color: #00c; +} + +#sync-setup-overlay * a:visited { + color: #551a8b; +} + +#sync-setup-overlay * a:active { + color: #f00; +} + +#sync-setup-overlay * hr { + background-color: #ddd; + border: 0; + height: 1px; + text-align: left; + width: 100%; +} + +#sync-setup-overlay * input[type='button'], +#sync-setup-overlay * input[type='submit'] { + min-height: 26px; + min-width: 87px; +} + +#sync-setup-overlay * .throbber { + margin: 4px 10px; + visibility: hidden; +} + +#email-readonly { + font-size: 15px; + height: 29px; + line-height: 29px; + margin: 0; +} + +#passphrase-encryption-message { + color: gray; + margin-bottom: 5px; +} + +#passphrase-input { + margin-top: 5px; + margin-bottom: 5px; +} + +#incorrect-passphrase { + margin-top: 5px; +} + +#sync-setup-overlay * .error { + color: red; +} + +.overlay-warning { + position: absolute; + left: 25px; + right: 25px; + top: 100px; + background: white; + border: 2px solid #888; + border-radius: 8px; + padding: 15px; + box-shadow: 0.2em 0.2em 0.5em #888; +} + +#cancel-warning-header { + font-weight: bold; + margin-bottom: 8px; +} + +.overlay-warning input { + margin-top: 12px; + float: right; + margin-left: 5px; +} + +#sync-passphrase-warning { + margin-bottom: 5px; +} + +#gaia-login-form { + margin-bottom: 0; +} + +#captcha-div { + border: 1px solid #e5e5e5; + background: #fff; + margin: 0 0 1.5em; + overflow: hidden; + padding: 1em 1em 0; +} + +#captcha-wrapper { + background: no-repeat; + background-position: center; + background-size: 200px 70px; + margin: 0 0 1em; +} + +#captcha-image { + height: 70px; + width: 200px; +} + +#asp-warning-div { + text-align: left; +} + +#logging-in-throbber { + margin: 0 10px; +} + +#top-blurb-error { + -webkit-transition: margin-top 330ms ease-out, opacity 660ms ease-out; + background: #f9edbe; + border: 1px solid #f0c36d; + display: block; + font-weight: bold; + line-height: 1.5em; + margin-bottom: 10px; + opacity: 1; + padding: 8px 25px; + position: relative; + text-align: center; +} + +#top-blurb-error[hidden] { + display: block; + margin-top: -37px; + opacity: 0; +} + +#password-row { + margin-top: 2px; +} + +#action-area { + margin-top: 2px; +} + +#sync-setup-configure { + line-height: 1.33em; + background: #fff; +} + +html[os='mac'] #sync-setup-configure { + line-height: 1.5em; +} + +#choose-data-types-form { + -webkit-user-select: none; +} + +#chooseDataTypesRadio { + vertical-align: top; +} + +#chooseDataTypes > div { + display: inline-block; +} + +.sync-item-show { + display: block; + white-space: nowrap; +} + +.sync-item-show > label { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + display: inline-block; + width: 92%; +} + +.sync-item-hide { + display: none; +} + +.sync-label-inactive { + color: #9b9b9b; +} + +.sync-label-active { + color: #000; +} + +.sync-data-types { + margin-left: 5px; +} + +.sync-configuration-errors { + margin-top: 5px; +} + +.sync-configuration-error { + width: 80%; + margin-left: auto; + margin-right: auto; + text-align: center; + padding: 1px 10px; + background-color: #eeb939; + border-radius: 4px; + font-weight: bold; +} + +#learn-more-link { + float: right; +} + +html[dir='rtl'] #learn-more-link { + float: left; +} + +#customize-link, #use-default-link { + -webkit-transition: opacity 250ms; +} + + +/* Sign in box. */ + +.sign-in { + margin: 20px auto; + width: 335px; +} + +.signin-box { + background: #f5f5f5; + border: 1px solid #e5e5e5; + padding: 20px 25px 15px; +} + +#signin-header { + position: relative; +} + +#signin-header h2 { + color: #222; + font-size: 16px; + font-weight: normal; + height: 16px; + line-height: 16px; + margin-top: 0; +} + +#signin-header-logo { + background: transparent + url('chrome://resources/images/google-transparent.png') no-repeat; + display: inline-block; + height: 19px; + position: absolute; + right: 0; + top: 1px; + width: 52px; +} + +html[dir='rtl'] #signin-header-logo { + left: 0; + right: auto; +} + +/* Sign in buttons. */ + +.signin-box input[type=submit] { + -webkit-transition: all 218ms; + -webkit-user-select: none; + background-image: -webkit-linear-gradient(top, #4d90fe, #4787ed); + border: 1px solid #3079ed; + border-radius: 2px; + color: #fff; + display: inline-block; + font-size: 13px; + font-weight: bold; + height: 32px; + line-height: 27px; + margin: 0 0.4em 1.2em 0; + min-width: 54px !important; + padding: 0 8px; +} + +html[dir='rtl'] .signin-box input[type=submit] { + margin: 0 0 1.2em 0.4em; +} + +.signin-box input[type=submit]:hover { + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); + -webkit-transition: all 0; + background-image: -webkit-linear-gradient(top, #4d90fe, #357ae8); + border: 1px solid #2f5bb7; + color: #fff; +} + +.signin-box input[type=submit]:focus { + -webkit-box-shadow: inset 0 0 0 1px #fff; + border: 1px solid #4d90fe; + outline: none; + z-index: 4 !important; +} + +.signin-box input[type=submit]:active, +.signin-box input[type=submit]:focus:active { + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); +} + +.signin-box input[type=submit]:focus:hover { + -webkit-box-shadow: inset 0 0 0 1px #fff, 0 1px 1px rgba(0, 0, 0, 0.1); +} + +.signin-box input[type=submit][disabled], +.signin-box input[type=submit][disabled]:hover, +.signin-box input[type=submit][disabled]:active { + -webkit-box-shadow: none; + background-color: #4d90fe; + border: 1px solid #3079ed; + color: #fff; + opacity: 0.5; +} + +/* Sign in text fields. */ + +.signin-box input[type=text], +.signin-box input[type=password] { + -webkit-border-radius: 1px; + -webkit-box-sizing: border-box; + background-color: #fff; + border: 1px solid #d9d9d9; + border-top: 1px solid #c0c0c0; + color: #333; + display: inline-block; + font-size: 15px; + height: 32px; + line-height: 27px; + margin-top: 0.5em; + padding-left: 8px; + vertical-align: top; + width: 100%; +} + +html[dir='rtl'] .signin-box input[type=text], +html[dir='rtl'] .signin-box input[type=password] { + padding-left: 0; + padding-right: 8px; +} + +.signin-box input[type=text]:hover, +.signin-box input[type=password]:hover { + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + border: 1px solid #b9b9b9; + border-top: 1px solid #a0a0a0; +} + +.signin-box input[type=text]:focus, +.signin-box input[type=password]:focus { + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); + border: 1px solid #4d90fe; + outline: none; +} + +.signin-box input[type=text][disabled], +.signin-box input[type=password][disabled] { + -webkit-box-shadow: none; + background: #f5f5f5; + border: 1px solid #e5e5e5; +} + +.signin-box input[type=text][disabled]:hover, +.signin-box input[type=password][disabled]:hover { + -webkit-box-shadow: none; +} + + +/* Sign in links. */ + +.signin-box .account-link { + color: #15c !important; + text-decoration: none; +} + +.signin-box .account-link:visited { + color: #61c !important; + text-decoration: none; +} + +.signin-box .account-link:hover { + text-decoration: underline; +} + +.signin-box .account-link:active { + color: #d14836 !important; + text-decoration: underline; +} + +/* Sign in text. */ + +.signin-box strong { + color: #222; + display: block; +} + +.signin-box label { + display: block; + margin: 0 0 1.5em; +} + +/* Sign in miscellaneous. */ + +.signin-box .throbber { + float: right; +} + +html[dir='rtl'] .signin-box .throbber { + float: left; +} + +#create-account-div { + display: inline-block; +} + +.signin-box .errormsg { + color: #dd4b39 !important; + font-size: 13px !important; + line-height: 17px; + margin: 0.5em 0 1.5em; +} + +.signin-box .help-link { + -webkit-border-radius: 1em; + background: #dd4b39; + color: #fff !important; + display: inline-block; + font-weight: bold; + padding: 0 5px; + position: relative; + text-decoration: none; + top: 0; +} + +.signin-box .help-link:visited { + color: #fff !important; +} + +.signin-box .help-link:hover { + color: #fff !important; + opacity: .7; +} + + + + +/* +Copyright (c) 2010 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.certificate-tree-table { + width: 100%; +} + +.certificate-tree { + /* TODO(mattm): BLAH. Make this not statically sized. */ + height: 300px; +} + + + span.certUntrusted { + background-color: pink; + border: 1px solid red; + border-radius: 3px; + margin-right: 3px; + padding-left: 1px; + padding-right: 1px; +} diff --git a/skin/prefs/prefs_legacy.css b/skin/prefs/prefs_legacy.css new file mode 100755 index 0000000..c797447 --- /dev/null +++ b/skin/prefs/prefs_legacy.css @@ -0,0 +1,2891 @@ +.bg-thumb { + max-height: 100px; + max-width: 100px; + vertical-align: middle; +} + +.hbox { + display: -webkit-box; + -webkit-box-orient: horizontal; +} + +.vbox { + display: -webkit-box; + -webkit-box-orient: vertical; +} + +.stretch { + -webkit-box-flex: 1; +} + +.frozen, +.subpage-sheet-container.frozen { + position: fixed; +} + +#search-field { + font-size: inherit; + margin: 0; +} + +/* + * Add padding to increase the touchable area of search box. Use original font + * size to avoid the width of search box exceeding the width of navbar. + */ +html[touch-optimized] #search-field { + font-size: 13px; + padding: 5px; +} +html[touch-optimized] #search-field::-webkit-search-cancel-button { + -webkit-transform: scale(1.5); +} + +/* + * For touch-optimized UI, make the radio/checkbox input boxes in + * options/preference pages easier to touch. + * TODO(rbyers): We need to solve this more generally for all web pages + * (crbug.com/99981), and perhaps temporarily for all WebUI (crbug.com/102482). + */ +html[touch-optimized] div.radio > label > span, +html[touch-optimized] div.checkbox > label > span { + -webkit-padding-start: 5px; +} + +html[touch-optimized] label > input[type=checkbox], +html[touch-optimized] label > input[type=radio] { + -webkit-transform: scale(1.4); +} + +/* + * Override the font-size rule in shared_options.css file. + * 16 px font-size proved to be more touch friendly. It increases the touchable + * area for buttons and input boxes. + */ +html[touch-optimized] body { + font-size: 16px; +} + +.overlay { + -webkit-box-align: center; + -webkit-box-orient: vertical; + -webkit-box-pack: center; + -webkit-transition: 250ms opacity; + background: -webkit-radial-gradient(rgba(127, 127, 127, 0.5), + rgba(127, 127, 127, 0.5) 35%, + rgba(0, 0, 0, 0.7)); + bottom: 0; + display: -webkit-box; + left: 0; + overflow: auto; + padding: 20px; + padding-bottom: 130px; + position: fixed; + right: 0; + top: 0; + z-index: 10; +} + +.raw-button, +.raw-button:hover, +.raw-button:active { + -webkit-box-shadow: none; + background-color: transparent; + background-repeat: no-repeat; + border: none; + min-width: 0; + padding: 1px 6px; +} + +.close-subpage { + background-image: url('chrome://theme/IDR_CLOSE_BAR'); + height: 16px; + min-width: 0; + position: relative; + top: 16px; + width: 16px; +} + +/* In TOUCH_UI builds, the IDR_CLOSE_BAR resource is double-size. */ + +.close-subpage:hover { + background-image: url('chrome://theme/IDR_CLOSE_BAR_H'); +} + +.close-subpage:active { + background-image: url('chrome://theme/IDR_CLOSE_BAR_P'); +} + +html[dir='ltr'] .close-subpage { + float: right; + right: 20px; +} + +html[dir='rtl'] .close-subpage { + float: left; + left: 20px; +} + +html.hide-menu .close-subpage { + display: none +} + +.content-area { + padding: 10px 15px 5px 15px; +} + +.action-area { + -webkit-box-align: center; + -webkit-box-orient: horizontal; + -webkit-box-pack: end; + border-top: 1px solid rgba(188, 193, 208, .5); + display: -webkit-box; + padding: 12px; +} + +html[dir='rtl'] .action-area { + left: 0; +} + +.action-area-right { + display: -webkit-box; +} + +.button-strip { + -webkit-box-orient: horizontal; + display: -webkit-box; +} + +.button-strip > button { + -webkit-margin-start: 10px; + display: block; +} + +.bottom-strip { + padding: 12px; + position: absolute; + right: 0px; + bottom: 0px; + border-top: none; +} + +.overlay .page { + -webkit-box-shadow: 0px 5px 80px #505050; + background: white; + border: 1px solid rgb(188, 193, 208); + border-radius: 2px; + min-width: 400px; + padding: 0; + position: relative; +} + +#subpage-backdrop { + -webkit-transition: 250ms opacity; + background-color: rgba(233, 238, 242, .5); + height: 100%; + left: 216px; + right: 216px; + position: fixed; + top: 0; + width: 100%; +} + +.subpage-sheet-container { + -webkit-transition: 250ms opacity, 100ms padding-left, 100ms padding-right; + box-sizing: border-box; + min-height: 100%; + position: absolute; + /* We set both left and right for the sake of RTL. */ + left: 0; + right: 0; + top: 0; + width: 100%; +} + +#subpage-sheet-container-1 { + -webkit-padding-start: 40px; + z-index: 5; +} + +#subpage-sheet-container-2 { + -webkit-padding-start: 80px; + z-index: 10; +} + +.subpage-sheet { + -webkit-box-shadow: #666 0px 2px 5px; + background-color: white; + border-left: 1px solid #b8b8b8; + box-sizing: border-box; + min-height: 100%; + width: 100%; + min-width: 651px; +} + +.subpage-sheet-contents { + box-sizing: border-box; + padding: 0px 20px 20px 20px; + width: 650px; +} + +.managed-prefs-banner { + background: -webkit-linear-gradient(#fff2b7, #fae691 97%, #878787); + height: 31px; + width: 100%; + margin: 0; + padding: 0; + position: relative; + vertical-align: middle; + z-index: 11; +} + +.managed-prefs-banner.clickable:active { + background: -webkit-linear-gradient(#878787, #fae691 3%, #fff2b7); +} + +.managed-prefs-icon { + background-image: url("chrome://theme/IDR_WARNING"); + background-repeat: no-repeat; + background-position:center; + display: inline-block; + padding: 5px; + height: 21px; + vertical-align: middle; + width: 24px; +} + +.managed-prefs-text { + vertical-align: middle; +} + +.subpage-sheet .page h1 { + margin-bottom: 10px; +} + +.overlay .page h1 { + background: -webkit-linear-gradient(white, #F8F8F8); + border-bottom: 1px solid rgba(188, 193, 208, .5); + font-size: 105%; + font-weight: bold; + padding: 10px 15px 8px 15px; +} + +.page list { + /* Min height is a multiple of the list item height (32) */ + min-height: 192px; +} + +/** + * TODO(kevers): Standardize formatting of sections to use display tables. + * For now, we require separate specialized rules for sections that are + * formatted as table rows. + */ +section { + -webkit-box-orient: horizontal; + border-bottom: 1px solid #eeeeee; + display: -webkit-box; + margin-top: 17px; + padding-bottom: 20px; +} + +div.page section:last-child { + border-bottom: none; +} + +h3 { + font-size: 105%; + font-weight: bold; + margin: 20px 0 10px 0; +} + +section > h3 { + margin: 0; + vertical-align: middle; + width: 130px; + -webkit-padding-end: 10px; +} + +section > div:only-of-type { + -webkit-box-flex: 1; +} + +/* Don't allow edge margin on the first/last child of a section. */ +section > h3 + * > *:last-child { + margin-bottom: 0; +} +section > h3 + * > *:first-child { + margin-top: 0; +} + +.option { + margin-top: 0; +} + +/* [hidden] does display:none, but its priority is too low in some cases. */ +[hidden] { + display: none !important; +} + +.transparent { + opacity: 0; +} + +.touch-slider { + -webkit-appearance: slider-horizontal; +} + +.settings-list, +.settings-list-empty { + border: 1px solid #d9d9d9; + border-radius: 2px; +} + +.settings-list-empty { + background-color: #f4f4f4; + box-sizing: border-box; + min-height: 125px; + padding-left: 20px; + padding-top: 20px; +} + +list > * { + -webkit-box-align: center; + -webkit-transition: 150ms background-color; + box-sizing: border-box; + border-radius: 0; + display: -webkit-box; + height: 32px; + border: none; + margin: 0; +} + +list:not([disabled]) > :hover { + background-color: #e4ecf7; +} + +/* TODO(stuartmorgan): Once this becomes the list style for other WebUI pages + * these rules can be simplified (since they wont need to override other rules). + */ + +list:not([hasElementFocus]) > [selected], +list:not([hasElementFocus]) > [lead][selected] { + background-color: #d0d0d0; + background-image: none; +} + +list[hasElementFocus] > [selected], +list[hasElementFocus] > [lead][selected], +list:not([hasElementFocus]) > [selected]:hover, +list:not([hasElementFocus]) > [selected][lead]:hover { + background-color: #bbcee9; + background-image: none; +} + +list[hasElementFocus] > [lead], +list[hasElementFocus] > [lead][selected] { + border-top: 1px solid #7892b4; + border-bottom: 1px solid #7892b4; +} + +list[hasElementFocus] > [lead]:nth-child(2), +list[hasElementFocus] > [lead][selected]:nth-child(2) { + border-top: 1px solid transparent; +} + +list[hasElementFocus] > [lead]:nth-last-child(2), +list[hasElementFocus] > [lead][selected]:nth-last-child(2) { + border-bottom: 1px solid transparent; +} + +list[disabled] > [lead][selected], +list[disabled]:focus > [lead][selected] { + border: none; +} + +list[disabled] { + opacity: 0.6; +} + +list > .heading { + color: #666666; +} + +list > .heading:hover { + background-color: transparent; + border-color: transparent; +} + +list .deletable-item { + -webkit-box-align: center; +} + +list .deletable-item > :first-child { + -webkit-box-align: center; + -webkit-box-flex: 1; + -webkit-padding-end: 5px; + display: -webkit-box; +} + +list .close-button { + -webkit-transition: 150ms opacity; + background-color: transparent; + /* TODO(stuartmorgan): Replace with real images once they are available. */ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAiElEQVR42r2RsQrDMAxEBRdl8SDcX8lQPGg1GBI6lvz/h7QyRRXV0qUULwfvwZ1tenw5PxToRPWMC52eA9+WDnlh3HFQ/xBQl86NFYJqeGflkiogrOvVlIFhqURFVho3x1moGAa3deMs+LS30CAhBN5nNxeT5hbJ1zwmji2k+aF6NENIPf/hs54f0sZFUVAMigAAAABJRU5ErkJggg=="); + border: none; + display: block; + height: 16px; + opacity: 1; + width: 16px; +} + +list > *:not(:hover):not([lead]) .close-button, +list > *:not(:hover):not([selected]) .close-button, +list:not([hasElementFocus]) > *:not(:hover) .close-button, +list[disabled] .close-button, +list .close-button[disabled] { + opacity: 0; + pointer-events: none; +} + +list .close-button:hover { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAqklEQVR4XqWRMQ6DMAxF/1Fyilyj2SmIBUG5QcTCyJA5Z8jGhlBPgRi4TmoDraVmKFJlWYrlp/g5QfwRlwEVNWVa4WzfH9jK6kCkEkBjwxOhLghheMWMELUAqqwQ4OCbnE4LJnhr5IYdqQt4DJQjhe9u4vBBmnxHHNzRFkDGjHDo0VuTAqy2vAG4NkvXXDHxbGsIGlj3e835VFNtdugma/Jk0eXq0lP//5svi4PtO01oFfYAAAAASUVORK5CYII="); +} + +list .close-button:active { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAARElEQVQoz2P4z4AfMlBLAYMdwxkghgEwD1XBGTC0g0sDIaYJECVwFqoChBK4WegKkJWArSJZAQErCDqSKG/iCyhaRhYA9LDIbULDzlIAAAAASUVORK5CYII="); +} + +list .static-text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +list[inlineeditable] input { + box-sizing: border-box; + margin: 0; + width: 100%; +} + +list > :not([editing]) [displaymode="edit"] { + display: none; +} + +list > [editing] [displaymode="static"] { + display: none; +} + +list > [editing] input:invalid { + /* TODO(stuartmorgan): Replace with validity badge */ + background-color: pink; +} + +.option-name { + padding-right: 5px; +} + +html[dir=rtl].option-name { + padding-left: 5px; +} + +.favicon-cell { + -webkit-padding-start: 20px; + background-position: left; + background-repeat: no-repeat; +} + +input[type="url"].favicon-cell { + -webkit-padding-start: 22px; + background-position-x: 4px; +} + +/* TODO(jhawkins): Use something better than 99.3% when CSS3 background + * positioning is available. + */ +html[dir=rtl] input.favicon-cell { + background-position-x: 99.3%; +} + +list .favicon-cell { + -webkit-margin-start: 7px; + -webkit-padding-start: 26px; + display: block; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +html[dir=rtl] list .favicon-cell { + background-position: right; +} + +html[enable-background-mode=false] #background-mode-section { + display: none; +} + +/* UI Controls */ + +/* LIST */ +html:not([os=mac]) list[hasElementFocus] { + outline: 1px solid rgba(0, 128, 256, 0.5); + outline-offset: -2px; +} + +/* This matches the native list outline on Mac */ +html[os=mac] list[hasElementFocus] { + outline-color: #759ad9; + outline-offset: -1px; + outline-style: auto; + outline-width: 5px; +} + +.suboption { + -webkit-margin-start: 23px; +} + +.informational-text { + color: grey; +} + +#main-content list.autocomplete-suggestions { + background-color: white; + border: 1px solid #aaa; + border-radius: 2px; + min-height: 0; + opacity: 0.9; + position: fixed; + z-index: 3; +} + +list.autocomplete-suggestions > div { + height: auto; +} + +list.autocomplete-suggestions:not([hasElementFocus]) > [selected], +list.autocomplete-suggestions:not([hasElementFocus]) > [lead][selected] { + background-color: #bbcee9; +} + +html:not([hasFlashPlugin]) .flash-plugin-area, +/* If the Flash plug-in supports the NPP_ClearSiteData API, we don't need to + * show the link to the Flash storage settings manager: + */ +html[flashPluginSupportsClearSiteData] .flash-plugin-area, +html:not([flashPluginSupportsClearSiteData]) .clear-plugin-lso-data-enabled, +html[flashPluginSupportsClearSiteData] .clear-plugin-lso-data-disabled { + display: none; +} + +/* Display a collection of sections as a table in order to display nicely + * in multiple locales. + */ +.displaytable { + display: table; + width: 100%; +} + +.displaytable > section { + display: table-row; +} + +/* right table column containing settable options */ +.displaytable > section > h3 + div, +.displaytable > section > h3 + table { + padding-bottom: 20px; +} + +/* Setting the padding on the header so the alignment doesn't depend on the + * contents of the right table column. */ +.displaytable > section > h3 { + padding-top: 17px; +} + +.displaytable > section > * { + display: table-cell; + vertical-align: baseline; + border-bottom: 1px solid #eeeeee; +} + +/* do not display a border after the last section in the table */ +.displaytable:not([searching='true']) > section:last-child > * { + border-bottom: none; +} + +/* Controlled setting indicator and bubble. */ +.controlled-setting-indicator { + display: inline-block; + /* Establish a containing block for absolutely positioning the bubble. */ + position: relative; + vertical-align: text-bottom; +} + +.controlled-setting-indicator[controlled-by] summary { + background-size: contain; + height: 16px; + width: 16px; +} + +.controlled-setting-indicator summary::-webkit-details-marker { + display: none; +} + +.controlled-setting-indicator[controlled-by='policy'] summary { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY_GRAY'); +} + +.controlled-setting-indicator[controlled-by='policy'] summary:hover { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY'); +} + +.controlled-setting-indicator[controlled-by='extension'] summary { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_EXTENSION_GRAY'); +} + +.controlled-setting-indicator[controlled-by='extension'] summary:hover { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_EXTENSION'); +} + +.controlled-setting-indicator[controlled-by='recommended'] summary { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_RECOMMENDED_GRAY'); +} + +.controlled-setting-indicator[controlled-by='recommended'] summary:hover { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_RECOMMENDED'); +} + +.controlled-setting-bubble { + -webkit-margin-start: -20px; + background-color: white; + border-radius: 4px; + border: 1px solid #ccc; + box-shadow: 0 2px 2px #ddd; + margin-top: 10px; + padding: 10px; + position: absolute; + top: 50%; + z-index: 10; +} + +html[dir='ltr'] .controlled-setting-bubble { + left: 50%; +} + +html[dir='rtl'] .controlled-setting-bubble { + right: 50%; +} + +.controlled-setting-bubble::before { + -webkit-margin-start: 4px; + border-color: #ccc transparent; + border-style: solid; + border-width: 0 5px 5px; + content: ''; + position: absolute; + top: -5px; +} + +.controlled-setting-bubble::after { + -webkit-margin-start: 5px; + border-color: white transparent; + border-style: solid; + border-width: 0 4px 4px; + content: ''; + position: absolute; + top: -4px; +} + +.controlled-setting-bubble-text { + -webkit-padding-start: 30px; + background-repeat: no-repeat; + margin: 0; + min-height: 32px; + min-width: 200px; +} + +.controlled-setting-indicator[controlled-by='policy'] + .controlled-setting-bubble-text { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY_LARGE'); +} + +.controlled-setting-indicator[controlled-by='extension'] + .controlled-setting-bubble-text { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_EXTENSION_LARGE'); +} + +.controlled-setting-indicator[controlled-by='recommended'] + .controlled-setting-bubble-text { + background-image: + url('chrome://theme/IDR_CONTROLLED_SETTING_RECOMMENDED_LARGE'); +} + +html[dir='rtl'] .controlled-setting-bubble-text { + background-position: right top; +} + +.controlled-setting-bubble-action { + padding: 0 !important; +} + +/* + * Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#advancedPage .section-group:not(:first-child) { + margin-top: 10px; +} + +#advancedPage .section-group:not(:last-child) { + margin-bottom: 10px; +} + +#advancedPage select, +#advancedPage .web-content-select-label { + min-width: 145px; +} + +#advancedPage .web-content-select-label > span:only-of-type { + display: inline-block; + min-width: 100px; +} + +#download-location-group { + margin: 10px 0 5px; + min-width: 470px; +} + +#fontSettingsCustomizeFontsButton, +#privacyClearDataButton { + margin-left: 10px; +} + +#alertOverlayMessage { + width: 400px; +} + +.autofill-list-item { + -webkit-box-flex: 1; + -webkit-padding-start: 8px; + overflow: hidden; + text-overflow: ellipsis; +} + +.autofill-list-item + img { + -webkit-padding-end: 20px; + vertical-align: middle; +} + +#autofill-options > div:last-child { + margin-top: 15px; +} + +#autofill-options > div.settings-list > div:last-child { + border-top: 1px solid #d9d9d9; + padding: 5px 10px; +} + +#autofill-add-address, +#autofill-add-creditcard { + margin: 2px 0; +} + +.autofill-list-item + button, +.autofill-list-item + img + button { + background: #8aaaed !important; /* Gets overwritten by raw-button:hover */ + color: #fff; + margin-top: 0; +} + +#address-list > div:not(:hover) * button, +#creditcard-list > div:not(:hover) * button { + display: none; +} + +#autofill-edit-address-overlay { + min-width: 510px; +} + +#autofill-edit-credit-card-overlay { + min-width: 500px; +} + +div.table { + display: table; +} + +div.cell { + display: table-cell; +} + +div.row { + display: table-row; +} + +div.input { + padding: 2px; +} + +/* Size to match large name fields. */ +#company-name, #addr-line-1, #addr-line-2 { + width: 206px; +} + +#country { + max-width: 450px; +} + +#autofill-edit-address-overlay list { + /* Min height is a multiple of the list item height (32) */ + min-height: 32px; + width: 176px; +} + +#autofill-edit-address-overlay list div.static-text { + -webkit-box-flex: 1; + -webkit-border-radius: 2px; + -webkit-padding-start: 4px; + -webkit-padding-end: 4px; + border: 1px solid darkGray; + /* Set the line-height and min-height to match the height of an input element, + * so that even empty cells renderer with the correct height. + */ + line-height: 1.75em; + min-height: 1.75em; + width: 141px; +} + +#autofill-edit-address-overlay list input { + width: 151px; +} + +#autofill-name-labels { + -webkit-box-orient: horizontal; + /* Set the margin to compensate for each list item's close button and + * padding. + */ + -webkit-margin-end: 25px; + display: -webkit-box; +} + +#autofill-name-labels label { + -webkit-box-flex: 1; + display: block; + /* Set the minimum width to the size of an input element, so that all boxes + * have an equal amount of flex space to work with. + */ + min-width: 141px; +} + +#autofill-edit-address-overlay list#full-name-list div.static-text { + width: 131px; +} + +#autofill-edit-address-overlay list#full-name-list input { + width: 141px; +} + +#autofill-edit-address-overlay list#full-name-list { + width: 100%; +} + +#full-name-list div[role="listitem"] > div { + -webkit-box-orient: horizontal; + display: -webkit-box; +} + +#full-name-list div[role="listitem"] > div > div { + -webkit-box-flex: 1; +} + +#startupPageManagement.settings-list > :last-child { + border-top: 1px solid #d9d9d9; + padding: 5px 10px; +} + +#startupPagesList { + min-height: 64px; +} + +#startupPagesList .title { + width: 40%; +} + +#startupPagesList .url { + -webkit-box-flex: 1; + color: #666; +} + +#startupPagesList > * { + max-width: 700px; +} + +#startupPagesListDropmarker { + background-clip: padding-box; + background-color: hsl(214, 91%, 65%); + border-bottom-color: transparent; + border-radius: 0; + border-top-color: transparent; + border: 2px solid hsl(214, 91%, 65%); + box-sizing: border-box; + display: none; + height: 6px; + overflow: hidden; + pointer-events: none; + position: fixed; + z-index: 10; +} + +#customHomePageGroup { + display: -webkit-box; + -webkit-box-orient: horizontal; +} + +#customHomePageGroup > :last-child { + -webkit-margin-start: 1ex; + -webkit-box-flex: 1; + position: relative; +} + +#homepageURL { + box-sizing: border-box; + padding-top: 3px; + width: 100%; +} + +#defaultSearchEngineGroup { + display: -webkit-box; + -webkit-box-orient: vertical; +} + +#defaultSearchEngineGroup > div { + display: -webkit-box; + -webkit-box-orient: horizontal; +} + +#defaultSearchEngine { + display: block; + -webkit-box-flex: 1; + max-width: 200px; +} + +#defaultSearchManageEnginesButton { + margin-top: 0px; + -webkit-margin-start: 10px; +} + +#defaultBrowserState { + margin-top: 6px; +} + +#instantOption { + margin-bottom: 3px; + margin-top: 10px +} + +#instantConfirmText { + font-family: inherit; + white-space: pre-wrap; + width: 500px; +} + +#instantConfirmLearnMore { + position: absolute; + bottom: 18px; +} + +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +#clearBrowserDataOverlay { + min-width: 500px; +} + +#clearBrowserDataOverlay > .content-area label { + margin: 5px 0; +} + +#clear-data-checkboxes { + -webkit-padding-start: 8px; + margin: 5px 0; +} + +#cbdThrobber { + margin: 4px 10px; + vertical-align: middle; + visibility: hidden; +} + +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.exception-pattern { + -webkit-box-flex: 1; + -webkit-margin-end: 10px; + -webkit-margin-start: 14px; +} + +.exception-setting { + display: inline-block; + width: 120px; +} + +select.exception-setting { + vertical-align: middle; +} + +#exception-column-headers { + -webkit-margin-start: 17px; + display: -webkit-box; + margin-top: 17px; +} + +#exception-column-headers > div { + font-weight: bold; +} + +#exception-pattern-column { + -webkit-box-flex: 1; +} + +#exception-behavior-column { + width: 145px; +} + +.otr-explanation { + font-style: italic; +} + +#content-settings-exceptions-area list { + margin-bottom: 10px; + margin-top: 4px; +} + +#disable-plugins-container { + margin: 7px 0px; +} + +div[role="listitem"][managedby] { + color: #666; + font-style: italic; + position: relative; +} + +.settings-list div[role="listitem"][managedby="policy"], +.settings-list div[role="listitem"][managedby="extension"] { + background: -webkit-linear-gradient(#fff1b5, #fae692); + border-top: 0; + border-bottom: 1px solid #c9bd8d; +} + +list div[role="listitem"][managedby="policy"] .close-button { + background-image: url("chrome://theme/IDR_MANAGED"); + opacity: 1; +} + +list div[role="listitem"][managedby="extension"] .close-button { + background-image: url("chrome://theme/IDR_EXTENSIONS_SECTION_SMALL"); + opacity: 1; +} + +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +/* styles for the cookies list elements in cookies_view.html */ +#remove-all-cookies-search-column { + bottom: 10px; + position: absolute; + right: 0; +} + +html[dir=rtl] #remove-all-cookies-search-column { + left: 0; + right: auto; +} + +#cookies-column-headers { + position: relative; + width: 100%; +} + +#cookies-column-headers h3 { + font-size: 105%; + font-weight: bold; + margin: 10px 0; +} + +/* notice the width and padding for these columns match up with those below */ +#cookies-site-column { + display: inline-block; + font-weight: bold; + width: 11em; +} + +#cookies-data-column { + -webkit-padding-start: 7px; + display: inline-block; + font-weight: bold; +} + +#cookies-list { + border: 1px solid #D9D9D9; + margin: 0; +} + +/* enable animating the height of items */ +list.cookie-list .deletable-item { + -webkit-transition: height .15s ease-in-out; +} + +/* disable webkit-box display */ +list.cookie-list .deletable-item > :first-child { + display: block; +} + +/* force the X for deleting an origin to stay at the top */ +list.cookie-list > .deletable-item > .close-button { + position: absolute; + right: 2px; + top: 8px; +} + +html[dir=rtl] list.cookie-list > .deletable-item > .close-button { + left: 2px; + right: auto; +} + +/* styles for the site (aka origin) and its summary */ +.cookie-site { + /* notice that the width, margin, and padding match up with those above */ + -webkit-margin-end: 2px; + -webkit-padding-start: 5px; + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + width: 11em; +} + +list.cookie-list > .deletable-item[selected] .cookie-site { + -webkit-user-select: text; +} + +.cookie-data { + display: inline-block; +} + +.cookie-size { + display: inline-block; + float: right; + margin-right: 3em; +} + +list.cookie-list > .deletable-item[selected] .cookie-data { + -webkit-user-select: text; +} + +/* styles for the individual items (cookies, etc.) */ +.cookie-items { + /* notice that the margin and padding match up with those above */ + -webkit-margin-start: 11em; + -webkit-padding-start: 7px; + -webkit-transition: .15s ease-in-out; + height: 0; + opacity: 0; + /* make the cookie items wrap correctly */ + white-space: normal; +} + +.measure-items .cookie-items { + -webkit-transition: none; + height: auto; + visibility: hidden; +} + +.show-items .cookie-items { + opacity: 1; +} + +.cookie-items .cookie-item { + background: #E0E9F5; + border-radius: 5px; + border: 1px solid #8392AE; + display: inline-block; + font-size: 85%; + height: auto; + margin: 2px 4px 2px 0; + max-width: 100px; + min-width: 40px; + overflow: hidden; + padding: 0 3px; + text-align: center; + text-overflow: ellipsis; +} + +.cookie-items .cookie-item:hover { + background: #EEF3F9; + border-color: #647187; +} + +.cookie-items .cookie-item[selected] { + background: #F5F8F8; + border-color: #B2B2B2; +} + +.cookie-items .cookie-item[selected]:hover { + background: #F5F8F8; + border-color: #647187; +} + +/* styles for the cookie details box */ +.cookie-details { + background: #F5F8F8; + border-radius: 5px; + border: 1px solid #B2B2B2; + margin-top: 2px; + padding: 5px; +} + +list.cookie-list > .deletable-item[selected] .cookie-details { + -webkit-user-select: text; +} + +.cookie-details-table { + table-layout: fixed; + width: 100%; +} + +.cookie-details-label { + vertical-align: top; + white-space: pre; + width: 10em; +} + +.cookie-details-value { + word-wrap: break-word; +} + +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.details-view { + -webkit-padding-end: 10px; +} + +.extension-list-item { + padding-bottom: 7px; + padding-top: 7px; + width: 100%; + -webkit-user-select: auto; +} + +/* Get rid of display: table, which causes width issues. */ +#extension-settings .displaytable { + display: block; +} +/* Get rid of display: table row, which causes width issues. */ +#extension-settings .displaytable > section { + display: block; +} +/* Get rid of display: table cell, which causes width issues. */ +#extension-settings .displaytable > section > * { + display: block; +} + +.extension-settings-content { + border-bottom : 0px solid #eee; + margin-top: 3px; +} + +#extension-settings-list { + min-height: 0; + overflow-y: hidden; +} + +/* Get rid of the light-blue background on list item hover. */ +#extension-settings-list:not([disabled]) > :hover { + background-color: white; + border-color: #CDCDCD; +} + +.butter-bar { + background: #FFF299; + padding: 2px 5px; + border-radius: 3px; + white-space: normal; +} + +.search-suppress { + display: none; + height: 0; +} + +.extension-list-item-collaped { + height: auto; + margin-bottom: 16px; + -webkit-transition: padding 300ms, overflow 300ms, opacity 700ms; +} + +.extension-list-item-expanded { + height: auto; + margin-bottom: 16px; + overflow: visible; + -webkit-transition: padding 300ms, overflow 300ms, opacity 700ms; +} + +.extension-settings { + overflow-x: hidden; +} + +.extension-icon { + height: 48px; + vertical-align: text-top; + width: 48px; + -webkit-padding-start: 15px; + -webkit-padding-end: 15px; + -webkit-user-select: none; +} + +.extension-title { + font-size: 16px; + font-weight: 500; + -webkit-padding-end: 20px; +} + +.extension-version { + font-size: 13px; + font-weight: 400; + -webkit-padding-end: 7px; +} + +.extension-description { + font-size: 13px; + white-space: normal; + -webkit-padding-end: 5px; +} + +.extension-checkbox-span { + -webkit-margin-start: 7px; +} + +.extension-checkbox-label { + -webkit-margin-end: 10px; +} + +.extension-delete { + -webkit-margin-start: 5px; +} + +.extension-details-hidden { + opacity: 0; + max-height: 0; + -webkit-transition: max-height 400ms, opacity 200ms; +} + +.extension-details-visible { + opacity: 1; + max-height: 1000px; + -webkit-transition: max-height 200ms, opacity 300ms; +} + +.extension-links-view { + -webkit-padding-start: 15px; +} + +.extension-links-trailing { + -webkit-padding-end: 7px; +} + +.extension-zippy-container { + cursor: pointer; + width: 20px; + -webkit-user-select: none; +} + +.extension-warnings-title { + color: red; +} + +.extension-warnings { + margin-top: 6px; +} + +.extension-warnings ul { + margin: 0; +} + +.extension-warnings > * { + white-space: normal; +} + +.informative-text { + color: gray; +} + +.extension-zippy-default { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAALCAYAAABcUvyWAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACsSURBVChTY3h778z/k9c+/EcHDFunB/5nYJb5f+bJdxQ5JnFpDQaGv08Y4sMDGK6++cMAA0z///8Ds68e3ckQGRLKcPbBR4jcqY1l/4EUHOs7+v+///zTfyZGuGYI4+L+jQwpM3YzMDEwoErxKFowhNrrgIyqgBvDLGP2f/6ea2DXMZzaVA6WYJc1/j977324kxkOLkkCSrD/n7TtBoo/GC7umva/Zf4lDJ8DAMX+kKcegZRQAAAAAElFTkSuQmCC"); + background-repeat: no-repeat; + background-position: center top; + position: absolute; + left: 12px; + top: 25px; + width: 6px; + height: 16px; + opacity: .25; +} + +.extension-zippy-collapsed { + -webkit-transition: -webkit-transform 100ms; + -webkit-transform: rotate(0deg); +} + +.extension-zippy-collapsed:hover { + opacity: .5; + -webkit-transform: rotate(5deg); + -webkit-transition: -webkit-transform 100ms, opacity 100ms; +} + +.extension-zippy-expanded { + -webkit-transition: -webkit-transform 100ms; + -webkit-transform: rotate(90deg); +} + +.extension-zippy-expanded:hover { + -webkit-transition: -webkit-transform 100ms; + -webkit-transform: rotate(85deg); +} + +.extension-enabling { + position: relative; + top: 3px; +} + +.extension-enabling-label { + color: black; + -webkit-padding-start: 3px; + -webkit-padding-end: 9px; +} + +.extension-enabling-label-bold { + font-weight: bold; +} + +.extension-inspect-table { + padding: 0; + border-spacing: 0; +} + +.extension-inspect-left-column { + vertical-align: text-top; +} + +/* Dev */ + +.dev-open { + border-bottom: 1px solid rgb(205, 205, 205); + height: 32px; + padding-bottom: 7px; + padding-top: 13px; + -webkit-padding-start: 4px; + -webkit-padding-end: 3px; + -webkit-transition: padding 300ms, height 300ms, opacity 700ms; +} +.dev-closed { + height: 0; + opacity: 0; + padding-top: 9px; + -webkit-padding-start: 4px; + -webkit-padding-end: 3px; + -webkit-transition: padding 300ms, height 700ms, opacity 200ms; +} + +.dev-button-visible { + display: inherit; + opacity: 1; + -webkit-transition: opacity 200ms; +} + +.dev-button-hidden { + display: none; +} + +#suggest-gallery { + -webkit-padding-start: 10px; +} + +#dev-toggle { + display: block; + text-align: end; + margin-top: -28px; + -webkit-margin-end: 8px; +} + +#get-more-extensions-container { + display: -webkit-box; +} + +#get-more-extensions { + padding-top: 5px; + font-size: 15px; + -webkit-padding-start: 10px; +} + +/* Support full keyboard accessibility without making things ugly + for users who click, by hiding some focus outlines when the user + clicks anywhere, but showing them when the user presses any key. */ +body.hide-some-focus-outlines .extension-zippy-container { + outline: none; +} + +#font-settings > section { + overflow: hidden; +} + +#font-settings input[type="range"] { + width: 100%; +} + +#minimum-font-sample { + height: 35px; + overflow: hidden; + width: 270px; +} + +.font-input-div { + -webkit-margin-end: 3em; + width: 12em; +} + +.font-input-div > div > select { + margin-bottom: 10px; +} + +.font-input { + width: 100%; +} + +.font-sample-div { + height: 70px; + overflow: hidden; + width: 270px; + direction: ltr; +} + +.font-settings-huge { + float: right; +} + +html[dir=rtl] .font-settings-huge { + float: left; +} + +/* + * Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +.handlers-column-headers { + display: -webkit-box; + font-size: 13px; + font-weight: bold; +} + +.handlers-type-column { + width: 100px; + -webkit-margin-end: 10px; + -webkit-margin-start: 14px; +} + +.handlers-site-column { + max-width: 180px; +} + +.handlers-site-column select { + max-width: 170px; +} + +.handlers-remove-column { + -webkit-box-flex: 1; +} + +.handlers-remove-link { + color: #555; + cursor: pointer; + opacity: 0; + padding-left: 14px; + text-decoration: underline; + -webkit-transition: 150ms opacity; +} + +div > .handlers-remove-column { + opacity: 0; +} + +div:not(.none):hover > .handlers-remove-column { + opacity: 1; +} + +#handlers { + min-height: 250px; +} + +#handler-options list { + border-radius: 2px; + border: solid 1px #D9D9D9; + margin-bottom: 10px; + margin-top: 4px; +} + +#import-from-div { + margin-bottom: 20px; +} + +#import-checkboxes > div:not(:first-child) { + -webkit-padding-start: 8px; + margin: 5px 0; +} + +#import-throbber { + margin: 4px 10px; + vertical-align: middle; + visibility: hidden; +} + +#import-success-header { + font-size: 1.2em; +} + +#import-success-image { + text-align: center; + margin: 20px; +} + +.language-options { + display: -webkit-box; + margin: 10px 0; +} + +.language-options-lower-left button, +.language-options-right button { + min-width: 70px; +} + +.language-options h3 { + -webkit-margin-start: 12px; + font-size: 100%; + font-weight: bold; + margin-top: 12px; +} + +.language-options-contents { + -webkit-padding-start: 12px; + -webkit-padding-end: 12px; + padding-bottom: 10px; +} + +.language-options-header, .language-options-footer { + margin: 10px 0; +} + +.language-options-left, .language-options-right { + border: 1px solid #cccccc; + vertical-align: top; + padding: 0; + height: 400px; +} + +.language-options-left { + -webkit-box-orient: vertical; + display: -webkit-box; + background-color: #ebeff9; + width: 300px; +} + +.language-options-lower-left { + -webkit-box-flex: 0; + -webkit-padding-start: 12px; + padding-bottom: 10px; +} + +.language-options-right { + /* To share the center line with the left pane. */ + -webkit-margin-start: -1px; + width: 360px; +} + +.language-options-notification { + display: none; + background-color: #fff29e; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + padding: 12px 30px 12px 12px; +} + +#language-options-input-method-list button { + display: block; + -webkit-margin-start: 20px; +} + +#language-options-ui-language-button { + width: 95%; + -webkit-margin-start: 10px; +} + +#language-options-spell-check-language-button { + width: 95%; + -webkit-margin-start: 10px; +} + +#language-options-input-method-list label { + margin: 4px 0; +} + +#language-options-list { + -webkit-box-flex: 1; + outline: none; + padding: 1px 0 0; + width: 100%; +} + +#language-options-list .language-name { + -webkit-box-flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#language-options-list li { + -webkit-padding-start: 12px; + padding-top: 2px; + padding-bottom: 2px; +} + +#language-options-list-dropmarker { + background-color: hsl(214, 91%, 65%); + background-clip: padding-box; + border: 3px solid hsl(214, 91%, 65%); + border-bottom-color: transparent; + border-top-color: transparent; + border-radius: 0; + box-sizing: border-box; + display: none; + height: 8px; + overflow: hidden; + pointer-events: none; + position: fixed; + z-index: 10; +} + +#language-options-ui-restart-button { + margin-top: 12px; +} + +/* + * In ChromeOS we present the language choices as a big page of links. + */ + +html[os=chromeos] #add-language-overlay-language-list { + -webkit-column-count: 2; + -webkit-column-gap: 20px; +} + +html[os=chromeos] #add-language-overlay-cancel-button { + /* Place the button in the center. */ + display: block; + margin: auto; + margin-top: 15px; +} + +html[os=chromeos] #add-language-overlay-page { + width: 800px; + padding: 20px; +} + +html[os=chromeos] #add-language-overlay-page button.link-button { + padding: 0; + text-align: left; +} + +html[os=chromeos] #add-language-overlay-page ul { + padding: 0; + margin: 0; +} + +/* TODO(kochi): This is temporary copy from new_tab.css */ +/* Notification */ + +#notification { + position: relative; + background-color: hsl(52, 100%, 80%); + border: 1px solid rgb(211, 211, 211); + border-radius: 6px; + padding: 7px 15px; + white-space: nowrap; + display: table; + /* Set the height and margin so that the element does not use any vertical + space */ + height: 16px; + margin: -44px auto 12px auto; + font-weight: bold; + opacity: 0; + pointer-events: none; + -webkit-transition: opacity 150ms; + z-index: 1; + color: black; +} + +#notification > * { + display: table-cell; + max-width: 500px; + overflow: hidden; + text-overflow: ellipsis; +} + +#notification.show { + opacity: 1; + pointer-events: all; + -webkit-transition: opacity 1s; +} + +#notification .link { + cursor: pointer; + text-decoration: underline; + -webkit-appearance: none; + border: 0; + background: none; + color: rgba(0, 102, 204, 0.3); + -webkit-padding-start: 20px; +} + +#notification .link-color { + color: rgb(0, 102, 204); +} + +#chewing-max-chi-symbol-len { + width: 100px; + height: 30%; +} + +#add-language-overlay-page .content-area { + padding-bottom: 10px; +} + +.text-button, +.text-button:active, +.text-button:focus, +.text-button:hover { + -webkit-box-shadow: none; + background: transparent none; + border-color: transparent; + color: #000; +} + +button[disabled].text-button, +button[disabled].text-button:active, +button[disabled].text-button:focus, +button[disabled].text-button:hover { + -webkit-box-shadow: none; + background: transparent none; + border-color: transparent; + color: #AAA; +} + +/* Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#manage-profile-overlay { + width: 500px; +} + +.profile-icon-grid-item { + border: none !important; + height: 31px; + margin: 4px 6px; + padding: 4px; + width: 38px; +} + +.profile-icon { + height: 31px; + width: 38px; +} + +#manage-profile-content > :first-child { + margin-bottom: 5px; +} + +#manage-profile-content > :last-child { + margin-top: 5px; +} + +#manage-profile-content > :not(:first-child):not(:last-child) { + margin-top: 5px; + margin-bottom: 5px; +} + +#manage-profile-name-div { + -webkit-box-align: baseline; + -webkit-box-orient: horizontal; + display: -webkit-box; +} + +#manage-profile-name-label { + -webkit-margin-end: 20px; +} + +#manage-profile-name { + -webkit-box-flex: 1; + display: block; +} + +#manage-profile-name:invalid { + background-color: pink; +} + +#manage-profile-error-bubble { + -webkit-transition: max-height 200ms, padding 200ms; + background-color: #eeb939; + border-radius: 4px; + font-weight: bold; + margin-left: auto; + margin-right: auto; + max-height: 50px; + overflow: hidden; + padding: 1px 10px; + text-align: center; + width: 80%; +} + +#manage-profile-error-bubble[hidden] { + display: block !important; + max-height: 0; + padding: 0 10px; +} + +#manage-profile-icon-grid { + background-color: rgba(255, 255, 255, 0.75); + border: 1px solid rgba(0, 0, 0, 0.3); + padding: 2px; +} + +#delete-profile-message { + background-repeat: no-repeat; + -webkit-padding-start: 48px; +} + +html[dir='rtl'] #delete-profile-message { + background-position: right; +} + +/* +Copyright (c) 2011 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.packExtensionHeading { + width: 520px; + padding-bottom: 5px; +} + +.packExtensionTextBoxes { + text-align: right; +} + +.packExtensionTextArea { + width: 260px; +} + +/* + * Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#password-search-column { + bottom: 10px; + position: absolute; + right: 0; +} + +html[dir=rtl] #password-search-column { + left: 0; + right: auto; +} + +#password-list-headers { + position: relative; + width: 100%; +} + +#password-list-headers h3 { + font-size: 105%; + font-weight: bold; + margin: 10px 0; +} + +#passwords-title { + display: inline-block; +} + +/* + * Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +button.password-button { + -webkit-transition: opacity .15s; + background: #8aaaed; + color: #fff; + display: inline; + font-size: 90%; + font-weight: bold; + height: 18px; + opacity: 0.3; + padding: 0 2px; + position: absolute; + top: 5px; +} + +button.password-button:hover { + -webkit-transition: opacity .15s; + opacity: 1; +} + +html[dir='ltr'] button.password-button { + right: 2px; +} + +html[dir='rtl'] button.password-button { + left: 2px; +} + +input[type="password"].inactive-password { + background: transparent; + border: none; +} + +#saved-passwords-list .url { + box-sizing: border-box; + width: 40%; +} + +#saved-passwords-list .name { + -webkit-box-flex: 1; + width: 20%; +} + +#saved-passwords-list .password { + -webkit-box-flex: 1; + position: relative; +} + +#saved-passwords-list .password input[type="password"], +#saved-passwords-list .password input[type="text"] { + box-sizing: border-box; + width: 100%; +} + +#password-exceptions-list .url { + -webkit-box-flex: 1; +} + +#saved-passwords-list .url, +#saved-passwords-list .name, +#password-exceptions-list .url { + overflow: hidden; + text-overflow: ellipsis; +} + +#account-picture-wrapper { + border-radius: 4px; + border: 1px solid rgba(0, 0, 0, 0.3); + display: inline-block; + margin: 5px 10px 5px 2px; + padding: 3px; +} + +#account-picture { + width: 70px; + height: 70px; + vertical-align: middle; +} + +#sync-buttons, #profiles-buttons { + margin-top: 10px; +} + +#start-stop-sync { + margin-left: 0; + margin-right: 5px; +} + +#profiles-list { + min-height: 0; + margin-bottom: 10px; +} + +#profiles-list > * { + height: 40px; +} + +.profile-img { + height: 31px; + padding: 3px; + vertical-align: middle; + width: 38px; +} + +.profile-item-current { + font-weight: bold; +} + +#themes-gallery-div { + margin: 10px 0; +} + +.sync-error { + background: #FFDBDB; + border: 1px solid #ce4c4c; + border-radius: 2px; + padding: 10px; +} + +.sync-error .link-button { + margin: 0 1ex; + padding: 0; +} + +#enable-auto-login-checkbox { + margin-top: 10px; +} + +#mac-passwords-warning { + margin-top: 10px; +} + +.search-engine-list > div { + display: -webkit-box; +} + +.search-engine-list .favicon { + padding: 1px 7px 0px 7px; + height: 16px; +} + +.search-engine-list .name-column { + -webkit-box-align: center; + -webkit-padding-end: 1ex; + box-sizing: border-box; + display: -webkit-box; + width: 37%; +} + +.search-engine-list .name-column :last-child { + -webkit-box-flex: 1; +} + +.search-engine-list .keyword-column { + -webkit-padding-end: 1ex; + box-sizing: border-box; + width: 26%; +} + +.search-engine-list .url-column { + box-sizing: border-box; + width: 37%; +} + +.search-engine-list .keyword-column, +.search-engine-list .url-column { + color: #666666; +} + +.search-engine-list .default .name-column, +.search-engine-list .default .keyword-column { + font-weight: bold; +} + +/* For temporary Make Default button */ +.search-engine-list .url-column { + display: -webkit-box; + -webkit-box-align: center; +} + +.search-engine-list .url-column :first-child { + -webkit-box-flex: 1; +} + +.search-engine-list .url-column button { + -webkit-margin-start: 3px; + background: #8aaaed; + color: #fff; + margin-top: 0; +} + +.search-engine-list > :not(:hover):not([editing]) .url-column button { + display: none; +} + +/* End temporary Make Default button styling */ + +.search-hidden { + display: none !important; +} + +.search-highlighted { + background-color: rgba(255, 240, 120, 0.9); +} + +.search-bubble { + -webkit-box-shadow: 0 2px 2px #888; + background-color: rgba(255, 240, 120, 0.8); + border-radius: 6px; + box-shadow: 0 2px 2px #888; + left: 0; + margin: 12px 0 0; + padding: 4px 10px; + pointer-events: none; + position: absolute; + text-align: center; + top: -1000px; /* minor hack: position off-screen by default */ + width: 100px; +} + +.search-bubble:after { + border-color: rgba(255, 240, 120, 0.9) transparent; + border-style: solid; + border-width: 0 10px 10px; + content: ""; + left: 50px; + position: absolute; + top: -10px; +} + +.search-bubble-wrapper { + position: relative; +} + +/* +Copyright (c) 2010 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.subpages-nav-tabs .tab { + position: relative; + padding: 4px 8px; +} + +.subpages-nav-tabs .active-tab { + position: relative; + background: white; + border: 1px solid #A0A0A0; /* light gray */ + border-bottom: 2px solid white; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +/* To avoid tabs changing size when they are clicked and their labels become + * bold, we actually put two labels inside each tab: an inactive label and an + * active label. Only one is visible at a time, but the bold label is used to + * size the tab even when it's not visible. This keeps the tab size constant. + */ +.subpages-nav-tabs .active-tab-label { + font-weight: bold; +} + +.subpages-nav-tabs .tab-label { + position: absolute; + top: 5px; + left: 9px; +} + +html[dir=rtl] .subpages-nav-tabs .tab-label { + right: 9px; +} + +.subpages-nav-tabs .active-tab-label, +.subpages-nav-tabs .active-tab .tab-label { + visibility: hidden; +} + +/* .tab is not removed when .active-tab is added, so we must + * override the hidden visibility above in the active tab case. + */ +.subpages-nav-tabs .active-tab .active-tab-label { + visibility: visible; +} + +.subpages-nav-tabs { + padding: 4px; + border-bottom: 1px solid #A0A0A0; /* light gray */ + background: -webkit-linear-gradient(white, #F3F3F3); /* very light gray */ + margin-bottom: 15px; +} + +.subpages-tab-contents { + display: none; + -webkit-padding-start: 10px; +} + +.active-tab-contents { + display: block; +} + +/* TODO(jhawkins): Organize these by page. */ + +#sync-setup-overlay * h4 { + margin: 5px 0; +} + +#sync-setup-overlay * form { + -webkit-user-select: none; +} + +#sync-setup-overlay * .content-area { + padding: 10px 15px; +} + +.action-area-link-container { + -webkit-box-flex: 1; +} + +.sync-customize-section-container { + margin: 5px 0 10px 0; +} + +#sync-custom-passphrase { + margin: 0 25px; +} + +#sync-passphrase-message { + color: gray; +} + +.sync-custom-passphrase-input { + margin: 10px 0; +} + +#sync-existing-passphrase-container { + background: #fff29e; + border: 1px solid #d4cdad; + padding: 10px; +} + +#sync-select-container { + margin-bottom: 10px; +} + +#sync-instructions-container { + margin-bottom: 30px; +} + +#choose-data-types-body { + margin: 10px 0; +} + +#choose-data-types-body > div { + -webkit-column-count: 3; +} + +#sync-setup-overlay { + -webkit-user-select: none; + background-color: #fff; + margin-bottom: 6px; + margin-top: 6px; + width: 500px; +} + +#sync-setup-overlay * a:link { + color: #00c; +} + +#sync-setup-overlay * a:visited { + color: #551a8b; +} + +#sync-setup-overlay * a:active { + color: #f00; +} + +#sync-setup-overlay * hr { + background-color: #ddd; + border: 0; + height: 1px; + text-align: left; + width: 100%; +} + +#sync-setup-overlay * input[type='button'], +#sync-setup-overlay * input[type='submit'] { + min-height: 26px; + min-width: 87px; +} + +#sync-setup-overlay * .throbber { + margin: 4px 10px; + visibility: hidden; +} + +#email-readonly { + font-size: 15px; + height: 29px; + line-height: 29px; + margin: 0; +} + +#passphrase-encryption-message { + color: gray; + margin-bottom: 5px; +} + +#passphrase-input { + margin-top: 5px; + margin-bottom: 5px; +} + +#incorrect-passphrase { + margin-top: 5px; +} + +#sync-setup-overlay * .error { + color: red; +} + +.overlay-warning { + position: absolute; + left: 25px; + right: 25px; + top: 100px; + background: white; + border: 2px solid #888; + border-radius: 8px; + padding: 15px; + box-shadow: 0.2em 0.2em 0.5em #888; +} + +#cancel-warning-header { + font-weight: bold; + margin-bottom: 8px; +} + +.overlay-warning input { + margin-top: 12px; + float: right; + margin-left: 5px; +} + +#sync-passphrase-warning { + margin-bottom: 5px; +} + +#gaia-login-form { + margin-bottom: 0; +} + +#captcha-div { + border: 1px solid #e5e5e5; + background: #fff; + margin: 0 0 1.5em; + overflow: hidden; + padding: 1em 1em 0; +} + +#captcha-wrapper { + background: no-repeat; + background-position: center; + background-size: 200px 70px; + margin: 0 0 1em; +} + +#captcha-image { + height: 70px; + width: 200px; +} + +#asp-warning-div { + text-align: left; +} + +#logging-in-throbber { + margin: 0 10px; +} + +#top-blurb-error { + -webkit-transition: margin-top 330ms ease-out, opacity 660ms ease-out; + background: #f9edbe; + border: 1px solid #f0c36d; + display: block; + font-weight: bold; + line-height: 1.5em; + margin-bottom: 10px; + opacity: 1; + padding: 8px 25px; + position: relative; + text-align: center; +} + +#top-blurb-error[hidden] { + display: block; + margin-top: -37px; + opacity: 0; +} + +#password-row { + margin-top: 2px; +} + +#action-area { + margin-top: 2px; +} + +#sync-setup-configure { + line-height: 1.33em; + background: #fff; +} + +html[os='mac'] #sync-setup-configure { + line-height: 1.5em; +} + +#choose-data-types-form { + -webkit-user-select: none; +} + +#chooseDataTypesRadio { + vertical-align: top; +} + +#chooseDataTypes > div { + display: inline-block; +} + +.sync-item-show { + display: block; + white-space: nowrap; +} + +.sync-item-show > label { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + display: inline-block; + width: 92%; +} + +.sync-item-hide { + display: none; +} + +.sync-label-inactive { + color: #9b9b9b; +} + +.sync-label-active { + color: #000; +} + +.sync-data-types { + margin-left: 5px; +} + +.sync-configuration-errors { + margin-top: 5px; +} + +.sync-configuration-error { + width: 80%; + margin-left: auto; + margin-right: auto; + text-align: center; + padding: 1px 10px; + background-color: #eeb939; + border-radius: 4px; + font-weight: bold; +} + +#learn-more-link { + float: right; +} + +html[dir='rtl'] #learn-more-link { + float: left; +} + +#customize-link, #use-default-link { + -webkit-transition: opacity 250ms; +} + +/* Sign in box. */ + +.sign-in { + margin: 20px auto; + width: 335px; +} + +.signin-box { + background: #f5f5f5; + border: 1px solid #e5e5e5; + padding: 20px 25px 15px; +} + +#signin-header { + position: relative; +} + +#signin-header h2 { + color: #222; + font-size: 16px; + font-weight: normal; + height: 16px; + line-height: 16px; + margin-top: 0; +} + +#signin-header-logo { + background: transparent + url('chrome://resources/images/google-transparent.png') no-repeat; + display: inline-block; + height: 19px; + position: absolute; + right: 0; + top: 1px; + width: 52px; +} + +html[dir='rtl'] #signin-header-logo { + left: 0; + right: auto; +} + +/* Sign in buttons. */ + +.signin-box input[type=submit] { + -webkit-transition: all 218ms; + -webkit-user-select: none; + background-image: -webkit-linear-gradient(top, #4d90fe, #4787ed); + border: 1px solid #3079ed; + border-radius: 2px; + color: #fff; + display: inline-block; + font-size: 13px; + font-weight: bold; + height: 32px; + line-height: 27px; + margin: 0 0.4em 1.2em 0; + min-width: 54px !important; + padding: 0 8px; +} + +html[dir='rtl'] .signin-box input[type=submit] { + margin: 0 0 1.2em 0.4em; +} + +.signin-box input[type=submit]:hover { + -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1); + -webkit-transition: all 0; + background-image: -webkit-linear-gradient(top, #4d90fe, #357ae8); + border: 1px solid #2f5bb7; + color: #fff; +} + +.signin-box input[type=submit]:focus { + -webkit-box-shadow: inset 0 0 0 1px #fff; + border: 1px solid #4d90fe; + outline: none; + z-index: 4 !important; +} + +.signin-box input[type=submit]:active, +.signin-box input[type=submit]:focus:active { + -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.3); +} + +.signin-box input[type=submit]:focus:hover { + -webkit-box-shadow: inset 0 0 0 1px #fff, 0px 1px 1px rgba(0, 0, 0, 0.1); +} + +.signin-box input[type=submit][disabled], +.signin-box input[type=submit][disabled]:hover, +.signin-box input[type=submit][disabled]:active { + -webkit-box-shadow: none; + background-color: #4d90fe; + border: 1px solid #3079ed; + color: #fff; + opacity: 0.5; +} + +/* Sign in text fields. */ + +.signin-box input[type=text], +.signin-box input[type=password] { + -webkit-border-radius: 1px; + -webkit-box-sizing: border-box; + background-color: #fff; + border: 1px solid #d9d9d9; + border-top: 1px solid #c0c0c0; + color: #333; + display: inline-block; + font-size: 15px; + height: 32px; + line-height: 27px; + margin-top: 0.5em; + padding-left: 8px; + vertical-align: top; + width: 100%; +} + +html[dir='rtl'] .signin-box input[type=text], +html[dir='rtl'] .signin-box input[type=password] { + padding-left: 0; + padding-right: 8px; +} + +.signin-box input[type=text]:hover, +.signin-box input[type=password]:hover { + -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1); + border: 1px solid #b9b9b9; + border-top: 1px solid #a0a0a0; +} + +.signin-box input[type=text]:focus, +.signin-box input[type=password]:focus { + -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.3); + border: 1px solid #4d90fe; + outline: none; +} + +.signin-box input[type=text][disabled], +.signin-box input[type=password][disabled] { + -webkit-box-shadow: none; + background: #f5f5f5; + border: 1px solid #e5e5e5; +} + +.signin-box input[type=text][disabled]:hover, +.signin-box input[type=password][disabled]:hover { + -webkit-box-shadow: none; +} + +/* Sign in links. */ + +.signin-box .account-link { + color: #15c !important; + text-decoration: none; +} + +.signin-box .account-link:visited { + color: #61c !important; + text-decoration: none; +} + +.signin-box .account-link:hover { + text-decoration: underline; +} + +.signin-box .account-link:active { + color: #d14836 !important; + text-decoration: underline; +} + +/* Sign in text. */ + +.signin-box strong { + color: #222; + display: block; +} + +.signin-box label { + display: block; + margin: 0 0 1.5em; +} + +/* Sign in miscellaneous. */ + +.signin-box .throbber { + float: right; +} + +html[dir='rtl'] .signin-box .throbber { + float: left; +} + +#create-account-div { + display: inline-block; +} + +.signin-box .errormsg { + color: #dd4b39 !important; + font-size: 13px !important; + line-height: 17px; + margin: 0.5em 0 1.5em; +} + +.signin-box .help-link { + -webkit-border-radius: 1em; + background: #dd4b39; + color: #fff !important; + display: inline-block; + font-weight: bold; + padding: 0 5px; + position: relative; + text-decoration: none; + top: 0; +} + +.signin-box .help-link:visited { + color: #fff !important; +} + +.signin-box .help-link:hover { + color: #fff !important; + opacity: .7; +} + +/* +Copyright (c) 2010 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +*/ + +.certificate-tree-table { + width: 100%; +} + +.certificate-tree { + /* TODO(mattm): BLAH. Make this not statically sized. */ + height: 300px; +} + +span.certUntrusted { + background-color: pink; + border: 1px solid red; + border-radius: 3px; + margin-right: 3px; + padding-left: 1px; + padding-right: 1px; +} + diff --git a/skin/prefs/prefs_new.css b/skin/prefs/prefs_new.css new file mode 100755 index 0000000..467dee8 --- /dev/null +++ b/skin/prefs/prefs_new.css @@ -0,0 +1,57 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#navigation { + height: 100%; + left: 0; + /* This is a hack to prevent the navigation bar from occluding pointer events + * from the bottom scroll bar (which shows when one needs to horizontally + * scroll). Corresponding padding-top to offset this is in uber_frame.css */ + margin-top: -20px; + position: absolute; + /* This value is different from the left value to compensate for the scroll + * bar (which is always on and to the right) in RTL. */ + right: 15px; + width: 155px; + z-index: 3; +} + +#navigation.background { + z-index: 1; +} + +#navigation.changing-content { + -webkit-transition: -webkit-transform 100ms, width 100ms; +} + +.iframe-container { + -webkit-margin-start: -20px; + -webkit-transition: margin 100ms, opacity 100ms; + bottom: 0; + left: 0; + opacity: 0; + position: absolute; + right: 0; + top: 0; + z-index: 1; +} + +.iframe-container.selected { + -webkit-margin-start: 0; + -webkit-transition: margin 200ms, opacity 200ms; + -webkit-transition-delay: 100ms; + opacity: 1; + z-index: 2; +} + +.iframe-container.expanded { + left: 0; +} + +iframe { + border: none; + display: block; + height: 100%; + width: 100%; +} diff --git a/skin/prefs/select.css b/skin/prefs/select.css new file mode 100755 index 0000000..8d1ad1b --- /dev/null +++ b/skin/prefs/select.css @@ -0,0 +1,52 @@ +/* Copyright (c) 2011 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * This is the generic select css used on various WebUI implementations. + */ + +select { + -webkit-appearance: button; + -webkit-border-radius: 3px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -webkit-padding-end: 20px; + -webkit-padding-start: 8px; + -webkit-user-select: none; + background-image: url("../images/select.png"), + -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5); + background-position: center right; + background-repeat: no-repeat; + border: 1px solid #aaa; + color: #555; + font-size: inherit; + margin: 0; + overflow: hidden; + padding-top: 2px; + padding-bottom: 2px; + text-overflow: ellipsis; + white-space: nowrap; +} + +html[dir='rtl'] select { + background-position: center left; +} + +select:disabled { + color: graytext; + background-image: url("../images/disabled_select.png"), + -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9); +} + +select:enabled:hover { + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + background-image: url("../images/select.png"), + -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9); + color: #333; +} + +select:enabled:active { + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); + background-image: url("../images/select.png"), + -webkit-linear-gradient(#f4f4f4, #efefef 40%, #dcdcdc); + color: #444; +} diff --git a/skin/prefs/select.png b/skin/prefs/select.png new file mode 100755 index 0000000..c20d304 Binary files /dev/null and b/skin/prefs/select.png differ diff --git a/skin/prefs/spinner.css b/skin/prefs/spinner.css new file mode 100755 index 0000000..f1df657 --- /dev/null +++ b/skin/prefs/spinner.css @@ -0,0 +1,16 @@ +.inline-spinner, +.spinner { + background-image: url('chrome://resources/images/spinner.svg'); + background-size: 100%; +} + +.inline-spinner { + display: inline-block; + height: 16px; + width: 16px; +} + +.spinner { + height: 22px; + width: 22px; +} diff --git a/skin/prefs/spinner.svg b/skin/prefs/spinner.svg new file mode 100755 index 0000000..d7c641e --- /dev/null +++ b/skin/prefs/spinner.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + diff --git a/skin/prefs/throbber.css b/skin/prefs/throbber.css new file mode 100755 index 0000000..8744040 --- /dev/null +++ b/skin/prefs/throbber.css @@ -0,0 +1,6 @@ +.throbber { + background: url('chrome://resources/images/throbber.svg'); + display: inline-block; + height: 16px; + width: 16px; +} diff --git a/skin/prefs/throbber.svg b/skin/prefs/throbber.svg new file mode 100755 index 0000000..efd7990 --- /dev/null +++ b/skin/prefs/throbber.svg @@ -0,0 +1,12 @@ + + + + + diff --git a/skin/prefs/tree.css b/skin/prefs/tree.css new file mode 100755 index 0000000..4718091 --- /dev/null +++ b/skin/prefs/tree.css @@ -0,0 +1,170 @@ +tree { + outline: none; + overflow: auto; + display: block; +} + +.tree-item > .tree-row { + color: black; + -webkit-user-select: none; + border: 1px solid rgba(255,255,255,0); /* transparent white */ + background-color: rgba(255,255,255,0); + border-radius: 2px; + padding: 0 3px; + line-height: 20px; + white-space: nowrap; + cursor: default; + position: relative; + margin: -1px 0; +} + +.expand-icon { + width: 16px; + height: 16px; + display: inline-block; + vertical-align: top; + position: relative; + top: 2px; + background-image: -webkit-canvas(tree-triangle); + background-position: 50% 50%; + background-repeat: no-repeat; + -webkit-transition: all .15s; + opacity: .6; + -webkit-transform: rotate(-90deg); +} + +html[dir=rtl] .expand-icon { + -webkit-transform: rotate(90deg); +} + +.tree-item[expanded] > .tree-row > .expand-icon { + background-image: -webkit-canvas(tree-triangle); + -webkit-transform: rotate(0deg); + opacity: .5; +} + +.tree-row .expand-icon { + visibility: hidden; +} + +.tree-row[may-have-children] .expand-icon { + visibility: visible; +} + +.tree-row[has-children=false] .expand-icon { + visibility: hidden; +} + +.tree-row:hover { + border-color: hsl(214, 91%, 85%); + z-index: 1; + background-color: hsl(214, 91%, 97%); +} + +/* + WebKit has a bug with attribute selectors so we apply selected to the tree row + as well. + + https://bugs.webkit.org/show_bug.cgi?id=12519 + +*/ +.tree-row[selected] { + background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.8), + rgba(255,255,255,0)); +} + +.tree-row[selected] { + border-color: hsl(0, 0%, 85%); + background-color: hsl(0, 0%, 90%); + z-index: 2; +} + +.tree-row[selected]:hover, +tree:focus .tree-row[selected] { + background-color: hsl(214, 91%, 89%); + border-color: #7da2ce; +} + +.tree-children[expanded] { + display: block; +} + +.tree-children { + display: none; +} + +.tree-item > .tree-row > * { + display: inline-block; + box-sizing: border-box; +} + +.tree-label { + -webkit-padding-start: 20px; + background-position: 0 50%; + background-repeat: no-repeat; + white-space: pre; +} + +html[dir=rtl] .tree-label { + background-position: 100% 50%; +} + +html[dir=rtl] .tree-label, +html[dir=rtl] .tree-row[may-have-children] > .tree-label { + background-image: url("../../../../../ui/resources/folder_closed_rtl.png"); +} + +html[dir=rtl] .tree-item[expanded] > .tree-row > .tree-label { + background-image: url("../../../../../ui/resources/folder_open_rtl.png"); +} + +tree[icon-visibility=hidden] .tree-label { + -webkit-padding-start: 0; + background-image: none !important; +} + +tree[icon-visibility=parent] .tree-label, +tree[icon-visibility=parent] .tree-row[has-children=false] > .tree-label { + background-image: none; +} + +.tree-label, +.tree-row[may-have-children] > .tree-label { + background-image: url("../../../../../ui/resources/folder_closed.png"); +} + +.tree-item[expanded] > .tree-row > .tree-label { + background-image: url("../../../../../ui/resources/folder_open.png"); +} + +/* We need to ensure that even empty labels take up space */ +.tree-label:empty:after { + content: " "; + white-space: pre; +} + +.tree-rename > .tree-row > .tree-label { + -webkit-user-select: auto; + -webkit-user-modify: read-write-plaintext-only; + background: white; + color: black; + outline: 1px solid black; +} + +.tree-item[editing] input { + /* Do not inherit the line-height */ + font-family: inherit; + font-size: inherit; + font-weight: inherit; + margin: -2px -8px -2px -3px; + padding: 1px 7px 1px 1px; +} + +html:not([os=mac]) .tree-item[editing] input { + outline: none; +} + +html[dir=rtl] .tree-item[editing] input { + margin: -2px -3px -2px -8px; + padding: 1px 1px 1px 7px; +} diff --git a/skin/prefs/widgets.css b/skin/prefs/widgets.css new file mode 100755 index 0000000..d8b2053 --- /dev/null +++ b/skin/prefs/widgets.css @@ -0,0 +1,297 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* This file defines styles for form controls. The order of rule blocks is + * important as there are some rules with equal specificity that rely on order + * as a tiebreaker. These are marked with OVERRIDE. + */ + +/* Default state **************************************************************/ + +button:not(.custom-appearance):not(.link-button), +input[type='button']:not(.custom-appearance):not(.link-button), +input[type='submit']:not(.custom-appearance):not(.link-button), +select, +input[type='checkbox'], +input[type='radio'] { + -webkit-appearance: none; + -webkit-user-select: none; + background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); + border: 1px solid rgba(0, 0, 0, 0.25); + border-radius: 2px; + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), + inset 0 1px 2px rgba(255, 255, 255, 0.75); + color: #444; + font: inherit; + margin: 0 1px 0 0; + text-shadow: 0 1px 0 rgb(240, 240, 240); +} + +button:not(.custom-appearance):not(.link-button), +input[type='button']:not(.custom-appearance):not(.link-button), +input[type='submit']:not(.custom-appearance):not(.link-button), +select { + min-height: 2em; + min-width: 4em; + + +} + +button:not(.custom-appearance):not(.link-button), +input[type='button']:not(.custom-appearance):not(.link-button), +input[type='submit']:not(.custom-appearance):not(.link-button) { + -webkit-padding-end: 10px; + -webkit-padding-start: 10px; +} + +select { + -webkit-appearance: none; + -webkit-padding-end: 20px; + -webkit-padding-start: 6px; + /* OVERRIDE */ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAWklEQVQokWNgoAOIAuI0PDiKaJMSgYCZmfkbkPkfHYPEQfJEG/b//3+FBQsWLGRjY/uJbBCIDxIHyRNtGDYDyTYI3UA+Pr4vFBmEbODbt2+bKDYIyUBWYtQBAIRzRP/XKJ//AAAAAElFTkSuQmCC"), + -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); + background-position: right center; + background-repeat: no-repeat; +} + +html[dir='rtl'] select { + background-position: center left; +} + +input[type='checkbox'] { + bottom: 2px; + height: 13px; + position: relative; + vertical-align: middle; + width: 13px; +} + +input[type='radio'] { + /* OVERRIDE */ + border-radius: 100%; + bottom: 3px; + height: 15px; + position: relative; + vertical-align: middle; + width: 15px; +} + +/* TODO(estade): add more types here? */ +input[type='password'], +input[type='search'], +input[type='text'], +input[type='url'], +input:not([type]) { + border: 1px solid #bfbfbf; + border-radius: 2px; + box-sizing: border-box; + color: #444; + font: inherit; + margin: 0; + /* Use min-height to accommodate addditional padding for touch as needed. */ + min-height: 2em; + padding: 3px; + + +} + +input[type='search'] { + -webkit-appearance: textfield; + /* NOTE: Keep a relatively high min-width for this so we don't obscure the end + * of the default text in relatively spacious languages (i.e. German). */ + min-width: 160px; +} + +/* Checked ********************************************************************/ + +input[type='checkbox']:checked::before { + -webkit-user-select: none; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wDBhYcG79aGIsAAACbSURBVBjTjdFBCkFhFAXgj4fp24PBy0SZ2ICRXRgYGb2xlKzBSEo2YgsiKWVoZgFKMjD5X/2Ux6lb99bpnNO5lKMR5i8MsEQHkhJiEzlS9HCqfiFWMUIt3AfsC3KKLCL30Qr7HfM4Ro4h6rhiEqmusIMKuphGqo+ogSPGcbYLzh91vdkXSHDDBk+0gxussS3rNcMCs+D6E18/9gLPPhbDshfzLgAAAABJRU5ErkJggg=="); + background-size: 100% 100%; + content: ''; + display: block; + height: 100%; + width: 100%; +} + +html[dir='rtl'] input[type='checkbox']:checked::before { + -webkit-transform: scaleX(-1); +} + +input[type='radio']:checked::before { + background-color: #666; + border-radius: 100%; + bottom: 25%; + content: ''; + display: block; + left: 25%; + position: absolute; + right: 25%; + top: 25%; +} + +/* Hover **********************************************************************/ + +button:not(.custom-appearance):not(.link-button):enabled:hover, +input[type='button']:not(.custom-appearance):not(.link-button):enabled:hover, +input[type='submit']:not(.custom-appearance):not(.link-button):enabled:hover, +select:enabled:hover, +input[type='checkbox']:enabled:hover, +input[type='radio']:enabled:hover { + background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); + border-color: rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), + inset 0 1px 2px rgba(255, 255, 255, 0.95); + color: black; +} + +select:enabled:hover { + /* OVERRIDE */ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAWklEQVQokWNgoAOIAuI0PDiKaJMSgYCZmfkbkPkfHYPEQfJEG/b//3+FBQsWLGRjY/uJbBCIDxIHyRNtGDYDyTYI3UA+Pr4vFBmEbODbt2+bKDYIyUBWYtQBAIRzRP/XKJ//AAAAAElFTkSuQmCC"), + -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); +} + +/* Active *********************************************************************/ + +button:not(.custom-appearance):not(.link-button):enabled:active, +input[type='button']:not(.custom-appearance):not(.link-button):enabled:active, +input[type='submit']:not(.custom-appearance):not(.link-button):enabled:active, +select:enabled:active, +input[type='checkbox']:enabled:active, +input[type='radio']:enabled:active { + background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); + box-shadow: none; + text-shadow: none; +} + +select:enabled:active { + /* OVERRIDE */ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAWklEQVQokWNgoAOIAuI0PDiKaJMSgYCZmfkbkPkfHYPEQfJEG/b//3+FBQsWLGRjY/uJbBCIDxIHyRNtGDYDyTYI3UA+Pr4vFBmEbODbt2+bKDYIyUBWYtQBAIRzRP/XKJ//AAAAAElFTkSuQmCC"), + -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); +} + +/* Disabled *******************************************************************/ + +button:not(.custom-appearance):not(.link-button):disabled, +input[type='button']:not(.custom-appearance):not(.link-button):disabled, +input[type='submit']:not(.custom-appearance):not(.link-button):disabled, +select:disabled { + background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6); + border-color: rgba(80, 80, 80, 0.2); + box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08), + inset 0 1px 2px rgba(255, 255, 255, 0.75); + color: #aaa; +} + +select:disabled { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAAXNSR0IArs4c6QAAAAd0SU1FB9sLAxYEBKriBmwAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAABLSURBVCiRY2CgA4gC4jQ8OIpokxKBoKGh4T8uDJIn2rD///8rLFiwYCE2g0DiIHkSfIndQLIMwmYgRQYhG/j27dsmig1CMpCVGHUAo8FcsHfxfXQAAAAASUVORK5CYII="), + -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6); +} + +input[type='checkbox']:disabled, +input[type='radio']:disabled { + opacity: .75; +} + +input[type='password']:disabled, +input[type='search']:disabled, +input[type='text']:disabled, +input[type='url']:disabled, +input:not([type]):disabled { + color: #999; +} + +/* Focus **********************************************************************/ + +button:not(.custom-appearance):not(.link-button):enabled:focus, +input[type='button']:not(.custom-appearance):enabled:focus, +input[type='checkbox']:enabled:focus, +input[type='password']:enabled:focus, +input[type='radio']:enabled:focus, +input[type='search']:enabled:focus, +input[type='submit']:not(.custom-appearance):enabled:focus, +input[type='text']:enabled:focus, +input[type='url']:enabled:focus, +input:not([type]):enabled:focus, +select:enabled:focus { + /* OVERRIDE */ + -webkit-transition: border-color 200ms; + /* We use border color because it follows the border radius (unlike outline). + * This is particularly noticeable on mac. */ + border-color: rgb(77, 144, 254); + outline: none; +} + +/* Link buttons ***************************************************************/ + +.link-button { + -webkit-box-shadow: none; + background: transparent none; + border: none; + color: rgb(17, 85, 204); + cursor: pointer; + /* Input elements have -webkit-small-control which can override the body font. + * Resolve this by using 'inherit'. */ + font: inherit; + margin: 0; + padding: 0 4px; +} + +.link-button:hover { + text-decoration: underline; +} + +.link-button:active { + color: rgb(5, 37, 119); + text-decoration: underline; +} + +.link-button[disabled] { + color: #999; + cursor: default; + text-decoration: none; +} + +/* Checkbox/radio helpers ****************************************************** + * + * .checkbox and .radio classes wrap labels. Checkboxes and radios should use + * these classes with the markup structure: + * + *
+ * + *
+ */ + +.checkbox, +.radio { + margin: 0.65em 0; +} + +.checkbox label, +.radio label { + /* Don't expand horizontally: . */ + display: -webkit-inline-box; +} + +.checkbox label input ~ span, +.radio label input ~ span { + -webkit-margin-start: 0.6em; + /* Make sure long spans wrap at the same horizontal position they start. */ + display: block; +} + +.checkbox label:hover, +.radio label:hover { + color: black; +} + +label > input[type=checkbox]:disabled ~ span, +label > input[type=radio]:disabled ~ span { + color: #999; +} diff --git a/skin/webstore.png b/skin/webstore.png new file mode 100644 index 0000000..28b90f2 Binary files /dev/null and b/skin/webstore.png differ diff --git a/skin/webstore_old.png b/skin/webstore_old.png new file mode 100755 index 0000000..5dffd46 Binary files /dev/null and b/skin/webstore_old.png differ diff --git a/skin/wrench.png b/skin/wrench.png new file mode 100755 index 0000000..94fa0eb Binary files /dev/null and b/skin/wrench.png differ