diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..1f77fee --- /dev/null +++ b/composer.json @@ -0,0 +1,20 @@ +{ + "name": "grent/simplesamlphp-module-themeopenaire", + "description": "A theme for SimpleSAMLphp based on Bootstrap", + "type": "simplesamlphp-module", + "keywords": ["simplesamlphp", "module", "theme", "bootstrap"], + "license": "Apache License 2.0", + "authors": [ + { + "name": "Athina Bekakou", + "email": "athinabek@grnet.gr" + }, + { + "name": "Nicolas Liampotis", + "email": "nliam@grnet.gr" + } + ], + "require": { + "simplesamlphp/composer-module-installer": "~1.0" + } +} diff --git a/default-enable b/default-enable new file mode 100644 index 0000000..e69de29 diff --git a/dictionaries/consent.definition.json b/dictionaries/consent.definition.json new file mode 100644 index 0000000..1b7f30c --- /dev/null +++ b/dictionaries/consent.definition.json @@ -0,0 +1,29 @@ +{ + "mandatory_field_error": { + "en": "Mandatory field!" + }, + "mail_field_error": { + "en": "Error in email" + }, + "terms_field_error": { + "en": "You must agree to continue" + }, + "affiliation_input_label": { + "en": "Organisation name" + }, + "header": { + "en": "We will be using the information below" + }, + "subheader": { + "en": "Please fill all missing information" + }, + "multiple_mails_tip": { + "en": "Choose your primary email address" + }, + "accept_terms_tip": { + "en": "Before continuing, you must agree to these terms. Please read them carefully" + }, + "terms_link_tip": { + "en": "here" + } +} diff --git a/dictionaries/discopower.definition.json b/dictionaries/discopower.definition.json new file mode 100644 index 0000000..3111b4a --- /dev/null +++ b/dictionaries/discopower.definition.json @@ -0,0 +1,12 @@ +{ + "header": { + "en": "Single Sign On" + }, + "subheader": { + "en": "Use the same credentials for all our services" + }, + "sign_up_url": { + "en": "https://beta.services.openaire.eu/uoa-user-management/register.jsp" + } +} + diff --git a/dictionaries/discopower_tabs.definition.json b/dictionaries/discopower_tabs.definition.json new file mode 100644 index 0000000..54f5c0e --- /dev/null +++ b/dictionaries/discopower_tabs.definition.json @@ -0,0 +1,47 @@ +{ + "norway": { + "en": "Norway" + }, + "kalmar": { + "en": "Kalmar" + }, + "finland": { + "en": "Finland" + }, + "sweden": { + "en": "Sweden" + }, + "iceland": { + "en": "Iceland" + }, + "denmark": { + "en": "Denmark" + }, + "switzerland": { + "en": "Switzerland" + }, + "edugain": { + "en": "Use your eduGAIN account" + }, + "misc": { + "en": "Miscellaneous" + }, + "incommon": { + "en": "InCommon" + }, + "ukacessfederation": { + "en": "UK Access Federation" + }, + "all": { + "en": "All" + }, + "social": { + "en": "Social Networks" + }, + "idps_with_logos": { + "en": "Use your account in social and other networks" + }, + "local": { + "en": "Use your OpenAIRE account" + } +} diff --git a/dictionaries/userid_error.definition.json b/dictionaries/userid_error.definition.json new file mode 100644 index 0000000..05f4832 --- /dev/null +++ b/dictionaries/userid_error.definition.json @@ -0,0 +1,20 @@ +{ + "friendly_title": { + "en": "Sorry, we were not able to log you in" + }, + "friendly_description": { + "en": "What is the problem? %IDP% does not return a persistent identifier to help us uniquely identify you." + }, + "resolution_description": { + "en": "What can you do? At the moment, the only way to log in is to use/create an OpenAIRE or social account. For future use, you may ask your institution administrator to release the required information, by sending them a print screen of this error, or asking them to contact our support at aai@openaire.eu." + }, + "details_title": { + "en": "Error details" + }, + "details_description": { + "en": "Your identity provider needs to release any of the following user identifiers to help us uniquely identify you:" + }, + "go2disco": { + "en": "Log in with a different account" + } +} diff --git a/themes/ssp/authX509/X509error.php b/themes/ssp/authX509/X509error.php new file mode 100644 index 0000000..b1e2f68 --- /dev/null +++ b/themes/ssp/authX509/X509error.php @@ -0,0 +1,41 @@ +data['header'] = $this->t('{authX509:X509error:certificate_header}'); + +$this->includeAtTemplateBase('includes/header.php'); + +?> + +data['errorcode'] !== NULL) { +?> +
+ +

t('{login:error_header}'); ?>

+

t('{errors:title_' . $this->data['errorcode'] . '}'); ?>

+

t('{errors:descr_' . $this->data['errorcode'] . '}'); ?>

+
+ +

t('{authX509:X509error:certificate_header}'); ?>

+ +

t('{authX509:X509error:certificate_text}'); ?>

+ + + t('{login:login_button}'); ?> + + +data['links'])) { + echo ''; +} + + + + +$this->includeAtTemplateBase('includes/footer.php'); diff --git a/themes/ssp/authorize/authorize_403.php b/themes/ssp/authorize/authorize_403.php new file mode 100644 index 0000000..08f8cad --- /dev/null +++ b/themes/ssp/authorize/authorize_403.php @@ -0,0 +1,28 @@ +data['403_header'] = $this->t('{authorize:Authorize:403_header}'); +$this->data['403_text'] = $this->t('{authorize:Authorize:403_text}'); + +$this->includeAtTemplateBase('includes/header.php'); +?> +

data['403_header']; ?>

+

data['403_text']; ?>

+data['LogoutURL'])) { +?> +

t('{status:logout}'); ?>

+ +includeAtTemplateBase('includes/footer.php'); diff --git a/themes/ssp/consent/consentform.php b/themes/ssp/consent/consentform.php new file mode 100644 index 0000000..9468bf1 --- /dev/null +++ b/themes/ssp/consent/consentform.php @@ -0,0 +1,326 @@ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+data["srcMetadata"])'); +assert('is_array($this->data["dstMetadata"])'); +assert('is_string($this->data["yesTarget"])'); +assert('is_array($this->data["yesData"])'); +assert('is_string($this->data["noTarget"])'); +assert('is_array($this->data["noData"])'); +assert('is_array($this->data["attributes"])'); +assert('is_array($this->data["hiddenAttributes"])'); +assert('$this->data["sppp"] === false || is_string($this->data["sppp"])'); + +// Parse parameters +if (array_key_exists('name', $this->data['srcMetadata'])) { + $srcName = $this->data['srcMetadata']['name']; +} elseif (array_key_exists('OrganizationDisplayName', $this->data['srcMetadata'])) { + $srcName = $this->data['srcMetadata']['OrganizationDisplayName']; +} else { + $srcName = $this->data['srcMetadata']['entityid']; +} + +if (is_array($srcName)) { + $srcName = $this->t($srcName); +} + +if (array_key_exists('name', $this->data['dstMetadata'])) { + $dstName = $this->data['dstMetadata']['name']; +} elseif (array_key_exists('OrganizationDisplayName', $this->data['dstMetadata'])) { + $dstName = $this->data['dstMetadata']['OrganizationDisplayName']; +} else { + $dstName = $this->data['dstMetadata']['entityid']; +} + +if (is_array($dstName)) { + $dstName = $this->t($dstName); +} + +$srcName = htmlspecialchars($srcName); +$dstName = htmlspecialchars($dstName); + +$attributes = $this->data['attributes']; + +$this->data['header'] = $this->t('{consent:consent:consent_header}'); +$this->data['jquery'] = array('core' => TRUE); + +$this->includeAtTemplateBase('includes/header.php'); +?> + +data['sppp'] !== false) { + echo "

" . htmlspecialchars($this->t('{consent:consent:consent_privacypolicy}')) . " "; + echo "" . $dstName . ""; + echo "

"; +} + +/** + * Recursive attribute array listing function + * + * @param SimpleSAML_XHTML_Template $t Template object + * @param array $attributes Attributes to be presented + * @param string $nameParent Name of parent element + * + * @return string HTML representation of the attributes + */ +function present_attributes($t, $attributes, $nameParent) +{ + $alternate = array('ssp-table--tr__odd', 'ssp-table--tr__even'); + $i = 0; + $summary = 'summary="' . $t->t('{consent:consent:table_summary}') . '"'; + + if (strlen($nameParent) > 0) { + $parentStr = strtolower($nameParent) . '_'; + $str = '
'; + } else { + $parentStr = ''; + $str = '
'; + } + + $mandatoryAttributeNames = array("sn", "mail", "givenName"); + $mandatoryAttributes = array(); + $editableAttributes = array("consentO"); + foreach($mandatoryAttributeNames as $el) { + $mandatoryAttributes[$el] = array(""); + } + if (empty($attributes['consentO']) && empty($attributes['o']) && empty($attributes['eduPersonScopedAffiliation']) && empty($attributes['eduPersonEntitlement'])) { + $attributes['consentO'] = array(""); + } + + $attributes = array_merge($mandatoryAttributes, $attributes); + + $attributeOrder = array( + 'sn', + 'givenName', + 'displayName', + 'mail', + 'eduPersonScopedAffiliation', + 'o', + 'consentO', + 'eduPersonEntitlement', + 'Entitlement', + 'eduPersonAssurance', + 'eduPersonUniqueId', + 'termsAccepted', + ); + $newAttributes = array(); + foreach ($attributeOrder as $attrKey) { + if (!empty($attributes[$attrKey])) { + $newAttributes[$attrKey] = $attributes[$attrKey]; + unset($attributes[$attrKey]); + } + } + $attributes = array_merge($newAttributes, $attributes); + + + + foreach ($attributes as $name => $value) { + $nameraw = $name; + $affliation = $name === 'eduPersonScopedAffiliation'; + $name = $t->getAttributeTranslation($parentStr . $nameraw); + $missing = $value[0] === '' && in_array($nameraw, $mandatoryAttributeNames); + $editable = in_array($nameraw, $editableAttributes); + $isHidden = in_array($nameraw, $t->data['hiddenAttributes'], true); + + + + if ($isHidden) { + continue; + } + + if (preg_match('/^child_/', $nameraw)) { + // insert child table + $parentName = preg_replace('/^child_/', '', $nameraw); + foreach ($value as $child) { + $str .= "\n" . ''; + } + } else { + // insert values directly + + if ($affliation) { + $str .= "\n" . ''; + } // end else: not child table + } // end foreach + $str .= isset($attributes)? '
' . + present_attributes($t, $child, $parentName) . '
' . $t->t('{themeopenaire:consent:affiliation_input_label}'); + } else { + $str .= "\n" . '
' . htmlspecialchars($name); + } + if ($missing) { + $str .= ' (*)'; + } + $str.= '
'; + + $str .= '
'; + + if (sizeof($value) > 1) { + // we hawe several values + $str .= '
    '; + $index = 0; + foreach ($value as $listitem) { + $index++; + if ($nameraw === 'jpegPhoto') { + $str .= '
  • User photo
  • '; + } elseif ($nameraw === 'mail') { + $str .= '
  • '; + $str .= '
'; + if ($nameraw === 'mail') { + $str .=''; + $str .= $t->t('{themeopenaire:consent:multiple_mails_tip}'); + $str .=''; + } + } elseif (isset($value[0])) { + // we hawe only one value + if ($nameraw === 'jpegPhoto') { + $str .= 'User photo'; + } elseif ($nameraw === 'termsAccepted') { + $str .='
data['termsName'])) { + $str .=' ' . $t->data['termsName']; + } + $str .= ''. + $t->t('{themeopenaire:consent:terms_field_error}'). + ''; + $str .= '
'; + if (!empty($t->data['termsUrl'])) { + $str .='
'; + $str .= $t->t('{themeopenaire:consent:accept_terms_tip}'); + $str .= ' '.$t->t('{themeopenaire:consent:terms_link_tip}').'.
'; + } + } elseif ($editable) { + $str .='
'; + } elseif ($missing) { + $str .='
'; + $str .=''. + $t->t('{themeopenaire:consent:mandatory_field_error}'). + ''; + if ($nameraw === 'mail') { + $str .= ''. + $t->t('{themeopenaire:consent:mail_field_error}'). + ''; + } + $str .='
'; + } else { + $str .= htmlspecialchars($value[0]); + } + + } // end of if multivalue + $str .= '
'; + $str .= '
':''; + return $str; +} + + echo '

' . + $this->t( + '{themeopenaire:consent:header}', + array( 'SPNAME' => $dstName, 'IDPNAME' => $srcName)). + '' . + $this->t( + '{themeopenaire:consent:subheader}', + array( 'SPNAME' => $dstName, 'IDPNAME' => $srcName)). + + '' . + '

+
+
'; +?> + + + +
+
+

+ +data['usestorage']) { + $checked = ($this->data['checked'] ? 'checked="checked"' : ''); + echo ' ' . $this->t('{consent:consent:remember}'); +} + +// Embed hidden fields... +foreach ($this->data['yesData'] as $name => $value) { + echo ''; +} +?> + +

+ + + +
+ +data['noData'] as $name => $value) { + echo(''); +} +?> + +
+
+
+
+includeAtTemplateBase('includes/footer.php'); +?> diff --git a/themes/ssp/consent/logout_completed.php b/themes/ssp/consent/logout_completed.php new file mode 100644 index 0000000..978931c --- /dev/null +++ b/themes/ssp/consent/logout_completed.php @@ -0,0 +1,9 @@ +data['header'] = $this->t('{logout:title}'); +$this->includeAtTemplateBase('includes/header.php'); + +echo('

' . $this->data['header'] . '

'); +echo('

' . $this->t('{logout:logged_out_text}') . '

'); + +$this->includeAtTemplateBase('includes/footer.php'); diff --git a/themes/ssp/consent/noconsent.php b/themes/ssp/consent/noconsent.php new file mode 100644 index 0000000..d4bc8fa --- /dev/null +++ b/themes/ssp/consent/noconsent.php @@ -0,0 +1,38 @@ +data['dstMetadata'])) { + $dstName = $this->data['dstMetadata']['name']; +} elseif (array_key_exists('OrganizationDisplayName', $this->data['dstMetadata'])) { + $dstName = $this->data['dstMetadata']['OrganizationDisplayName']; +} else { + $dstName = $this->data['dstMetadata']['entityid']; +} +if (is_array($dstName)) { + $dstName = $this->t($dstName); +} +$dstName = htmlspecialchars($dstName); + + +$this->data['header'] = $this->t('{consent:consent:noconsent_title}');; + +$this->includeAtTemplateBase('includes/header.php'); + +echo '

' . $this->data['header'] . '

'; +echo '

' . $this->t('{consent:consent:noconsent_text}', array('SPNAME' => $dstName)) . '

'; + +echo '
'; +if ($this->data['resumeFrom']) { + echo(''); + echo($this->t('{consent:consent:noconsent_return}')); + echo(''); +} + +if ($this->data['aboutService']) { + echo(''); + echo($this->t('{consent:consent:noconsent_goto_about}')); + echo(''); +} +echo('' . $this->t('{consent:consent:abort}', array('SPNAME' => $dstName)) . ''); +echo '
'; //ssp-btns-container + +$this->includeAtTemplateBase('includes/footer.php'); diff --git a/themes/ssp/core/no_cookie.tpl.php b/themes/ssp/core/no_cookie.tpl.php new file mode 100644 index 0000000..3836fa9 --- /dev/null +++ b/themes/ssp/core/no_cookie.tpl.php @@ -0,0 +1,22 @@ +data)'); +$retryURL = $this->data['retryURL']; + +$header = htmlspecialchars($this->t('{core:no_cookie:header}')); +$description = htmlspecialchars($this->t('{core:no_cookie:description}')); +$retry = htmlspecialchars($this->t('{core:no_cookie:retry}')); + +$this->data['header'] = $header; +$this->includeAtTemplateBase('includes/header.php'); + +echo('

' . $header . '

'); +echo('

' . $description . '

'); + +if ($retryURL !== NULL) { + echo(''); +} + +$this->includeAtTemplateBase('includes/footer.php'); diff --git a/themes/ssp/core/no_metadata.tpl.php b/themes/ssp/core/no_metadata.tpl.php new file mode 100644 index 0000000..dd38399 --- /dev/null +++ b/themes/ssp/core/no_metadata.tpl.php @@ -0,0 +1,9 @@ +' . $this->t('{core:no_metadata:config_problem}') . '

'); + +echo(''); + diff --git a/themes/ssp/core/no_state.tpl.php b/themes/ssp/core/no_state.tpl.php new file mode 100644 index 0000000..f8ba2d6 --- /dev/null +++ b/themes/ssp/core/no_state.tpl.php @@ -0,0 +1,15 @@ +' . $this->t('{core:no_state:suggestions}') . ''); +echo(''); + +echo('

' . $this->t('{core:no_state:causes}') . '

'); +echo(''); + diff --git a/themes/ssp/default/error.php b/themes/ssp/default/error.php new file mode 100644 index 0000000..30e3303 --- /dev/null +++ b/themes/ssp/default/error.php @@ -0,0 +1,78 @@ +data['header'] = $this->t($this->data['dictTitle']); +$this->data['jquery'] = array('core' => TRUE); + +$this->data['head'] = << + +EOF; + +$this->includeAtTemplateBase('includes/header.php'); +?> +

t($this->data['dictTitle']); ?>

+t($this->data['dictDescr'], $this->data['parameters'])); + +// include optional information for error +if (isset($this->data['includeTemplate'])) { + $this->includeAtTemplateBase($this->data['includeTemplate']); +} +?> +
+

t('report_trackid'); ?>

+
+ + + +
+
+data['showerrors']) { +?> +

t('debuginfo_header'); ?>

+

t('debuginfo_text'); ?>

+ +
+

data['error']['exceptionMsg']); ?>

+
data['error']['exceptionTrace']); ?>
+
+data['errorReportAddress'])) { +?> +

t('report_header'); ?>

+
+

t('report_text'); ?>

+

t('report_email'); ?> + +

+

+ +

+

+ + +

+
+ +

t('howto_header'); ?>

+

t('howto_text'); ?>

+ +includeAtTemplateBase('includes/footer.php'); diff --git a/themes/ssp/default/includes/footer.php b/themes/ssp/default/includes/footer.php new file mode 100644 index 0000000..eb68779 --- /dev/null +++ b/themes/ssp/default/includes/footer.php @@ -0,0 +1,30 @@ + +data['htmlinject']['htmlContentPost'])) { + foreach($this->data['htmlinject']['htmlContentPost'] AS $c) { + echo $c; + } +} +?> + + + + + + + + + diff --git a/themes/ssp/default/includes/header.php b/themes/ssp/default/includes/header.php new file mode 100644 index 0000000..260077a --- /dev/null +++ b/themes/ssp/default/includes/header.php @@ -0,0 +1,141 @@ +data['htmlinject'] = array( + 'htmlContentPre' => array(), + 'htmlContentPost' => array(), + 'htmlContentHead' => array(), +); + + +$jquery = array(); +if (array_key_exists('jquery', $this->data)) $jquery = $this->data['jquery']; + +if (array_key_exists('pageid', $this->data)) { + $hookinfo = array( + 'pre' => &$this->data['htmlinject']['htmlContentPre'], + 'post' => &$this->data['htmlinject']['htmlContentPost'], + 'head' => &$this->data['htmlinject']['htmlContentHead'], + 'jquery' => &$jquery, + 'page' => $this->data['pageid'] + ); + + SimpleSAML_Module::callHooks('htmlinject', $hookinfo); +} +// - o - o - o - o - o - o - o - o - o - o - o - o - + +/** + * Do not allow to frame SimpleSAMLphp pages from another location. + * This prevents clickjacking attacks in modern browsers. + * + * If you don't want any framing at all you can even change this to + * 'DENY', or comment it out if you actually want to allow foreign + * sites to put SimpleSAMLphp in a frame. The latter is however + * probably not a good security practice. + */ +header('X-Frame-Options: SAMEORIGIN'); + +?> + + + + + +OpenAIRE Single Sign-On Service | <?php +if(array_key_exists('header', $this->data)) { + echo $this->data['header']; +} else { + echo 'SimpleSAMLphp'; +} +?> + + + + +data['baseurlpath'] . 'resources/jquery-1.8.js">' . "\n"); + + if (isset($jquery['ui']) && $jquery['ui']) + echo('' . "\n"); + + if (isset($jquery['css']) && $jquery['css']) + echo('' . "\n"); + } +} + +if (isset($this->data['clipboard.js'])) { + echo ''."\n"; +} + +if(!empty($this->data['htmlinject']['htmlContentHead'])) { + foreach($this->data['htmlinject']['htmlContentHead'] AS $c) { + echo $c; + } +} + + + + +if ($this->isLanguageRTL()) { +?> + + + + + + + +data)) { + echo '' . $this->data['head'] . ''; +} +?> + +data)) { + $onLoad .= 'SimpleSAML_focus(\'' . $this->data['autofocus'] . '\');'; +} +if (isset($this->data['onLoad'])) { + $onLoad .= $this->data['onLoad']; +} + +if($onLoad !== '') { + $onLoad = ' onload="' . $onLoad . '"'; +} +?> +> + +
+ +
+
+ + +data['htmlinject']['htmlContentPre'])) { + foreach($this->data['htmlinject']['htmlContentPre'] AS $c) { + echo $c; + } +} diff --git a/themes/ssp/discopower/disco-tpl.php b/themes/ssp/discopower/disco-tpl.php new file mode 100644 index 0000000..c02155a --- /dev/null +++ b/themes/ssp/discopower/disco-tpl.php @@ -0,0 +1,307 @@ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+data['idplist'] AS $tab => $slist) { + if (!empty($this->data['preferredidp']) && array_key_exists($this->data['preferredidp'], $slist)) + $faventry = $slist[$this->data['preferredidp']]; +} + + +if(!array_key_exists('header', $this->data)) { + $this->data['header'] = 'selectidp'; +} +$this->data['header'] = $this->t($this->data['header']); +$this->data['jquery'] = array('core' => TRUE, 'ui' => TRUE, 'css' => TRUE); + + +$this->data['head'] = ''; +$this->data['head'] .= ''; + +if (!empty($faventry)) $this->data['autofocus'] = 'favouritesubmit'; + +$this->includeAtTemplateBase('includes/header.php'); + +echo '

' . $this->t('{themeopenaire:discopower:header}') . '

'; + +$languages_html = ''; +$includeLanguageBar = TRUE; +if (!empty($_POST)) + $includeLanguageBar = FALSE; +if (isset($this->data['hideLanguageBar']) && $this->data['hideLanguageBar'] === TRUE) + $includeLanguageBar = FALSE; + +if ($includeLanguageBar) { + + $languages = $this->getLanguageList(); + if ( count($languages) > 1 ) { + $languages_html .= '
+
'; + $langnames = array( + 'no' => 'Bokmål', // Norwegian Bokmål + 'nn' => 'Nynorsk', // Norwegian Nynorsk + 'se' => 'Sámegiella', // Northern Sami + 'sam' => 'Åarjelh-saemien giele', // Southern Sami + 'da' => 'Dansk', // Danish + 'en' => 'English', + 'de' => 'Deutsch', // German + 'sv' => 'Svenska', // Swedish + 'fi' => 'Suomeksi', // Finnish + 'es' => 'Español', // Spanish + 'fr' => 'Français', // French + 'it' => 'Italiano', // Italian + 'nl' => 'Nederlands', // Dutch + 'lb' => 'Lëtzebuergesch', // Luxembourgish + 'cs' => 'Čeština', // Czech + 'sl' => 'Slovenščina', // Slovensk + 'lt' => 'Lietuvių kalba', // Lithuanian + 'hr' => 'Hrvatski', // Croatian + 'hu' => 'Magyar', // Hungarian + 'pl' => 'Język polski', // Polish + 'pt' => 'Português', // Portuguese + 'pt-br' => 'Português brasileiro', // Portuguese + 'ru' => 'русский язык', // Russian + 'et' => 'eesti keel', // Estonian + 'tr' => 'Türkçe', // Turkish + 'el' => 'ελληνικά', // Greek + 'ja' => '日本語', // Japanese + 'zh' => '简体中文', // Chinese (simplified) + 'zh-tw' => '繁體中文', // Chinese (traditional) + 'ar' => 'العربية', // Arabic + 'fa' => 'پارسی', // Persian + 'ur' => 'اردو', // Urdu + 'he' => 'עִבְרִית', // Hebrew + 'id' => 'Bahasa Indonesia', // Indonesian + 'sr' => 'Srpski', // Serbian + 'lv' => 'Latviešu', // Latvian + 'ro' => 'Românește', // Romanian + 'eu' => 'Euskara', // Basque + ); + + $textarray = array(); + foreach ($languages AS $lang => $current) { + $lang = strtolower($lang); + if ($current) { + $lang_current = $langnames[$lang]; + } else { + $textarray[] = '
  • ' . + $langnames[$lang] . '
  • '; + } + } + $languages_html .= ' +
    '; // /dropup /ssp-lang-container + } +} + + + +function showEntry($t, $metadata, $favourite = FALSE) { + + $basequerystring = '?' . + 'entityID=' . urlencode($t->data['entityID']) . '&' . + 'return=' . urlencode($t->data['return']) . '&' . + 'returnIDParam=' . urlencode($t->data['returnIDParam']) . '&idpentityid='; + + $providersOnlyIcon = array("google", "linkedin", "facebook", "orcid", "igtf_certificate_proxy"); + $providerLocal = "openaire"; + $namelower_dasherize = str_replace(' ', '_', strtolower(getTranslatedName($t, $metadata))); + + + if(in_array($namelower_dasherize, $providersOnlyIcon)) { + $html = ''; + $html .= 'Identity Provider'; + $html .= ''; + } + else if($namelower_dasherize == $providerLocal) { + $html = ''; + $html .= 'Identity Provider'; + $html .= 'OpenAIRE account'; + $html .= ''; + } + else { + $html = ''; + $html .= htmlspecialchars(getTranslatedName($t, $metadata)) . ''; + + if(array_key_exists('icon', $metadata) && $metadata['icon'] !== NULL) { + $iconUrl = \SimpleSAML\Utils\HTTP::resolveURL($metadata['icon']); + $html .= 'Identity Provider'; + } + + $html .= ''; + } + + + + return $html; +} + +?> + + + + translation + if (!empty($displayName)) { + return $t->getTranslation($displayName); + } + } + + if (array_key_exists('name', $metadata)) { + if (is_array($metadata['name'])) { + return $t->getTranslation($metadata['name']); + } else { + return $metadata['name']; + } + } + return $metadata['entityid']; +} + + +echo('
    '); + +$or_html = '
    +
    or
    +
    '; + +$edugain_html = ''; +$local_html =''; +$idps_with_logo_html = ''; +if (!empty($faventry)) { + echo(' + + '); +} + + +foreach( $this->data['idplist'] AS $tab => $slist) { + if ($tab !== 'all') { + if (!empty($slist)) { + if($tab == 'edugain') { + $edugainList = '
    '; + if (!empty($this->data['preferredidp']) && array_key_exists($this->data['preferredidp'], $slist)) { + $idpentry = $slist[$this->data['preferredidp']]; + $edugainList .= (showEntry($this, $idpentry, TRUE)); + } + + foreach ($slist AS $idpentry) { + if ($idpentry['entityid'] != $this->data['preferredidp']) { + $edugainList .= (showEntry($this, $idpentry)); + } + } + $edugainList .= '
    '; // /metalist + $buttonOpenEdugain = '

    Log in with

    '; + $edugain_html .= ' + '; + $edugain_html .= $buttonOpenEdugain; + } + else if($tab == "idps_with_logos") { + $providers = ''; + if (!empty($this->data['preferredidp']) && array_key_exists($this->data['preferredidp'], $slist)) { + $idpentry = $slist[$this->data['preferredidp']]; + $providers .= (showEntry($this, $idpentry, TRUE)); + } + + foreach ($slist AS $idpentry) { + if ($idpentry['entityid'] != $this->data['preferredidp']) { + $providers .= (showEntry($this, $idpentry)); + } + } + $idps_with_logo_html .= '
    ' + . $providers . + '
    '; + } + else if($tab == "local") { + $providers = ''; + // Should be 1 provider in the list + foreach ($slist AS $idpentry) { + $providers .= (showEntry($this, $idpentry)); + } + $local_html .= '
    ' + . $providers . + '
    '; + } + } + } +} + echo $edugain_html . $idps_with_logo_html . $or_html . $local_html; +?> + +
    + +includeAtTemplateBase('includes/footer.php'); diff --git a/themes/ssp/userid/error.tpl.php b/themes/ssp/userid/error.tpl.php new file mode 100644 index 0000000..4ebd363 --- /dev/null +++ b/themes/ssp/userid/error.tpl.php @@ -0,0 +1,42 @@ +data['header'] = $this->t('{userid:error:header}'); +$this->data['jquery'] = array('core' => TRUE); + +$this->data['head'] = << + +EOF; + +$this->includeAtTemplateBase('includes/header.php'); +$retryUrl = $this->data['parameters']['%BASEDIR%'] . 'saml2/idp/initSLO.php?RelayState=' . urlencode($this->data['parameters']['%RESTARTURL%']); +?> +
    +
    + ' . $this->t('{themeopenaire:userid_error:friendly_title}') . ''; + echo $friendly_title; + ?> +

    t('{themeopenaire:userid_error:friendly_description}', $this->data['parameters']); ?>

    +

    t('{themeopenaire:userid_error:resolution_description}', array('%RETRY_URL%' => $retryUrl)); ?>

    +
    +
    + +
    +
    +

    t('{themeopenaire:userid_error:details_title}'); ?>

    +

    t('{themeopenaire:userid_error:details_description}'); ?>

    +
    +      data['parameters']['%ATTRIBUTES%'] as $attr) echo $attr . '
    '; ?> +
    +
    +
    +includeAtTemplateBase('includes/footer.php'); diff --git a/www/resources/OpenMinTeD_Logo-300x300.png b/www/resources/OpenMinTeD_Logo-300x300.png new file mode 100644 index 0000000..f228c43 Binary files /dev/null and b/www/resources/OpenMinTeD_Logo-300x300.png differ diff --git a/www/resources/OpenMinTeD_Logo-50x50.png b/www/resources/OpenMinTeD_Logo-50x50.png new file mode 100644 index 0000000..f4306af Binary files /dev/null and b/www/resources/OpenMinTeD_Logo-50x50.png differ diff --git a/www/resources/OpenMinTeD_Logo-80x60.png b/www/resources/OpenMinTeD_Logo-80x60.png new file mode 100644 index 0000000..c561ef2 Binary files /dev/null and b/www/resources/OpenMinTeD_Logo-80x60.png differ diff --git a/www/resources/OpenMinTeD_Logo-90x90.png b/www/resources/OpenMinTeD_Logo-90x90.png new file mode 100644 index 0000000..7830b33 Binary files /dev/null and b/www/resources/OpenMinTeD_Logo-90x90.png differ diff --git a/www/resources/fonts/bootstrap/glyphicons-halflings-regular.eot b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..b93a495 Binary files /dev/null and b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.eot differ diff --git a/www/resources/fonts/bootstrap/glyphicons-halflings-regular.svg b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..94fb549 --- /dev/null +++ b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/www/resources/fonts/bootstrap/glyphicons-halflings-regular.ttf b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..1413fc6 Binary files /dev/null and b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.ttf differ diff --git a/www/resources/fonts/bootstrap/glyphicons-halflings-regular.woff b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..9e61285 Binary files /dev/null and b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.woff differ diff --git a/www/resources/fonts/bootstrap/glyphicons-halflings-regular.woff2 b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000..64539b5 Binary files /dev/null and b/www/resources/fonts/bootstrap/glyphicons-halflings-regular.woff2 differ diff --git a/www/resources/images/OpenAIRE_Logo-120x120.png b/www/resources/images/OpenAIRE_Logo-120x120.png new file mode 100644 index 0000000..aa66f65 Binary files /dev/null and b/www/resources/images/OpenAIRE_Logo-120x120.png differ diff --git a/www/resources/images/OpenAIRE_Logo-300x300.png b/www/resources/images/OpenAIRE_Logo-300x300.png new file mode 100644 index 0000000..beaed4a Binary files /dev/null and b/www/resources/images/OpenAIRE_Logo-300x300.png differ diff --git a/www/resources/images/OpenAIRE_Logo-50x50.png b/www/resources/images/OpenAIRE_Logo-50x50.png new file mode 100644 index 0000000..2389adc Binary files /dev/null and b/www/resources/images/OpenAIRE_Logo-50x50.png differ diff --git a/www/resources/images/OpenAIRE_Logo-80x60.png b/www/resources/images/OpenAIRE_Logo-80x60.png new file mode 100644 index 0000000..4c6bdbc Binary files /dev/null and b/www/resources/images/OpenAIRE_Logo-80x60.png differ diff --git a/www/resources/images/edugain.png b/www/resources/images/edugain.png new file mode 100644 index 0000000..552ed85 Binary files /dev/null and b/www/resources/images/edugain.png differ diff --git a/www/resources/images/facebook.jpg b/www/resources/images/facebook.jpg new file mode 100644 index 0000000..b37d9de Binary files /dev/null and b/www/resources/images/facebook.jpg differ diff --git a/www/resources/images/favicon.ico b/www/resources/images/favicon.ico new file mode 100644 index 0000000..cd00609 Binary files /dev/null and b/www/resources/images/favicon.ico differ diff --git a/www/resources/images/google.jpg b/www/resources/images/google.jpg new file mode 100644 index 0000000..7873e85 Binary files /dev/null and b/www/resources/images/google.jpg differ diff --git a/www/resources/images/linkedin.jpg b/www/resources/images/linkedin.jpg new file mode 100644 index 0000000..049a74a Binary files /dev/null and b/www/resources/images/linkedin.jpg differ diff --git a/www/resources/images/logo.png b/www/resources/images/logo.png new file mode 100644 index 0000000..797a31b Binary files /dev/null and b/www/resources/images/logo.png differ diff --git a/www/resources/images/openaire.png b/www/resources/images/openaire.png new file mode 100644 index 0000000..aa66f65 Binary files /dev/null and b/www/resources/images/openaire.png differ diff --git a/www/resources/images/orcid.jpg b/www/resources/images/orcid.jpg new file mode 100644 index 0000000..10c3bbd Binary files /dev/null and b/www/resources/images/orcid.jpg differ diff --git a/www/resources/js/.theme.js.un~ b/www/resources/js/.theme.js.un~ new file mode 100644 index 0000000..50f0f9d Binary files /dev/null and b/www/resources/js/.theme.js.un~ differ diff --git a/www/resources/js/dropdown.js b/www/resources/js/dropdown.js new file mode 100644 index 0000000..04e9c2d --- /dev/null +++ b/www/resources/js/dropdown.js @@ -0,0 +1,165 @@ +/* ======================================================================== + * Bootstrap: dropdown.js v3.3.7 + * http://getbootstrap.com/javascript/#dropdowns + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle="dropdown"]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.VERSION = '3.3.7' + + function getParent($this) { + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = selector && $(selector) + + return $parent && $parent.length ? $parent : $this.parent() + } + + function clearMenus(e) { + if (e && e.which === 3) return + $(backdrop).remove() + $(toggle).each(function () { + var $this = $(this) + var $parent = getParent($this) + var relatedTarget = { relatedTarget: this } + + if (!$parent.hasClass('open')) return + + if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return + + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this.attr('aria-expanded', 'false') + $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) + }) + } + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $(document.createElement('div')) + .addClass('dropdown-backdrop') + .insertAfter($(this)) + .on('click', clearMenus) + } + + var relatedTarget = { relatedTarget: this } + $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this + .trigger('focus') + .attr('aria-expanded', 'true') + + $parent + .toggleClass('open') + .trigger($.Event('shown.bs.dropdown', relatedTarget)) + } + + return false + } + + Dropdown.prototype.keydown = function (e) { + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return + + var $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + if (!isActive && e.which != 27 || isActive && e.which == 27) { + if (e.which == 27) $parent.find(toggle).trigger('focus') + return $this.trigger('click') + } + + var desc = ' li:not(.disabled):visible a' + var $items = $parent.find('.dropdown-menu' + desc) + + if (!$items.length) return + + var index = $items.index(e.target) + + if (e.which == 38 && index > 0) index-- // up + if (e.which == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 + + $items.eq(index).trigger('focus') + } + + + // DROPDOWN PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.dropdown') + + if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + var old = $.fn.dropdown + + $.fn.dropdown = Plugin + $.fn.dropdown.Constructor = Dropdown + + + // DROPDOWN NO CONFLICT + // ==================== + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + // APPLY TO STANDARD DROPDOWN ELEMENTS + // =================================== + + $(document) + .on('click.bs.dropdown.data-api', clearMenus) + .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) + +}(jQuery); diff --git a/www/resources/js/modal.js b/www/resources/js/modal.js new file mode 100644 index 0000000..f84142d --- /dev/null +++ b/www/resources/js/modal.js @@ -0,0 +1,339 @@ +/* ======================================================================== + * Bootstrap: modal.js v3.3.7 + * http://getbootstrap.com/javascript/#modals + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // MODAL CLASS DEFINITION + // ====================== + + var Modal = function (element, options) { + this.options = options + this.$body = $(document.body) + this.$element = $(element) + this.$dialog = this.$element.find('.modal-dialog') + this.$backdrop = null + this.isShown = null + this.originalBodyPad = null + this.scrollbarWidth = 0 + this.ignoreBackdropClick = false + + if (this.options.remote) { + this.$element + .find('.modal-content') + .load(this.options.remote, $.proxy(function () { + this.$element.trigger('loaded.bs.modal') + }, this)) + } + } + + Modal.VERSION = '3.3.7' + + Modal.TRANSITION_DURATION = 300 + Modal.BACKDROP_TRANSITION_DURATION = 150 + + Modal.DEFAULTS = { + backdrop: true, + keyboard: true, + show: true + } + + Modal.prototype.toggle = function (_relatedTarget) { + return this.isShown ? this.hide() : this.show(_relatedTarget) + } + + Modal.prototype.show = function (_relatedTarget) { + var that = this + var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) + + this.$element.trigger(e) + + if (this.isShown || e.isDefaultPrevented()) return + + this.isShown = true + + this.checkScrollbar() + this.setScrollbar() + this.$body.addClass('modal-open') + + this.escape() + this.resize() + + this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) + + this.$dialog.on('mousedown.dismiss.bs.modal', function () { + that.$element.one('mouseup.dismiss.bs.modal', function (e) { + if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true + }) + }) + + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + if (!that.$element.parent().length) { + that.$element.appendTo(that.$body) // don't move modals dom position + } + + that.$element + .show() + .scrollTop(0) + + that.adjustDialog() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + that.enforceFocus() + + var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) + + transition ? + that.$dialog // wait for modal to slide in + .one('bsTransitionEnd', function () { + that.$element.trigger('focus').trigger(e) + }) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + that.$element.trigger('focus').trigger(e) + }) + } + + Modal.prototype.hide = function (e) { + if (e) e.preventDefault() + + e = $.Event('hide.bs.modal') + + this.$element.trigger(e) + + if (!this.isShown || e.isDefaultPrevented()) return + + this.isShown = false + + this.escape() + this.resize() + + $(document).off('focusin.bs.modal') + + this.$element + .removeClass('in') + .off('click.dismiss.bs.modal') + .off('mouseup.dismiss.bs.modal') + + this.$dialog.off('mousedown.dismiss.bs.modal') + + $.support.transition && this.$element.hasClass('fade') ? + this.$element + .one('bsTransitionEnd', $.proxy(this.hideModal, this)) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + this.hideModal() + } + + Modal.prototype.enforceFocus = function () { + $(document) + .off('focusin.bs.modal') // guard against infinite focus loop + .on('focusin.bs.modal', $.proxy(function (e) { + if (document !== e.target && + this.$element[0] !== e.target && + !this.$element.has(e.target).length) { + this.$element.trigger('focus') + } + }, this)) + } + + Modal.prototype.escape = function () { + if (this.isShown && this.options.keyboard) { + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { + e.which == 27 && this.hide() + }, this)) + } else if (!this.isShown) { + this.$element.off('keydown.dismiss.bs.modal') + } + } + + Modal.prototype.resize = function () { + if (this.isShown) { + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) + } else { + $(window).off('resize.bs.modal') + } + } + + Modal.prototype.hideModal = function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.$body.removeClass('modal-open') + that.resetAdjustments() + that.resetScrollbar() + that.$element.trigger('hidden.bs.modal') + }) + } + + Modal.prototype.removeBackdrop = function () { + this.$backdrop && this.$backdrop.remove() + this.$backdrop = null + } + + Modal.prototype.backdrop = function (callback) { + var that = this + var animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $(document.createElement('div')) + .addClass('modal-backdrop ' + animate) + .appendTo(this.$body) + + this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { + if (this.ignoreBackdropClick) { + this.ignoreBackdropClick = false + return + } + if (e.target !== e.currentTarget) return + this.options.backdrop == 'static' + ? this.$element[0].focus() + : this.hide() + }, this)) + + if (doAnimate) this.$backdrop[0].offsetWidth // force reflow + + this.$backdrop.addClass('in') + + if (!callback) return + + doAnimate ? + this.$backdrop + .one('bsTransitionEnd', callback) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callback() + + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass('in') + + var callbackRemove = function () { + that.removeBackdrop() + callback && callback() + } + $.support.transition && this.$element.hasClass('fade') ? + this.$backdrop + .one('bsTransitionEnd', callbackRemove) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callbackRemove() + + } else if (callback) { + callback() + } + } + + // these following methods are used to handle overflowing modals + + Modal.prototype.handleUpdate = function () { + this.adjustDialog() + } + + Modal.prototype.adjustDialog = function () { + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight + + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' + }) + } + + Modal.prototype.resetAdjustments = function () { + this.$element.css({ + paddingLeft: '', + paddingRight: '' + }) + } + + Modal.prototype.checkScrollbar = function () { + var fullWindowWidth = window.innerWidth + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 + var documentElementRect = document.documentElement.getBoundingClientRect() + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) + } + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth + this.scrollbarWidth = this.measureScrollbar() + } + + Modal.prototype.setScrollbar = function () { + var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) + this.originalBodyPad = document.body.style.paddingRight || '' + if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) + } + + Modal.prototype.resetScrollbar = function () { + this.$body.css('padding-right', this.originalBodyPad) + } + + Modal.prototype.measureScrollbar = function () { // thx walsh + var scrollDiv = document.createElement('div') + scrollDiv.className = 'modal-scrollbar-measure' + this.$body.append(scrollDiv) + var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth + this.$body[0].removeChild(scrollDiv) + return scrollbarWidth + } + + + // MODAL PLUGIN DEFINITION + // ======================= + + function Plugin(option, _relatedTarget) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.modal') + var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('bs.modal', (data = new Modal(this, options))) + if (typeof option == 'string') data[option](_relatedTarget) + else if (options.show) data.show(_relatedTarget) + }) + } + + var old = $.fn.modal + + $.fn.modal = Plugin + $.fn.modal.Constructor = Modal + + + // MODAL NO CONFLICT + // ================= + + $.fn.modal.noConflict = function () { + $.fn.modal = old + return this + } + + + // MODAL DATA-API + // ============== + + $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { + var $this = $(this) + var href = $this.attr('href') + var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 + var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) + + if ($this.is('a')) e.preventDefault() + + $target.one('show.bs.modal', function (showEvent) { + if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown + $target.one('hidden.bs.modal', function () { + $this.is(':visible') && $this.trigger('focus') + }) + }) + Plugin.call($target, option, this) + }) + +}(jQuery); diff --git a/www/resources/js/theme.js b/www/resources/js/theme.js new file mode 100644 index 0000000..a93b4e3 --- /dev/null +++ b/www/resources/js/theme.js @@ -0,0 +1,191 @@ +// Make one element to get all the available height +function spreadHeight($el2spread) { + var el2spread_height = $el2spread.height(), + $parent = $el2spread.parent(), + parent_height = $parent.height(), + $siblings = $el2spread.siblings().not('.modal'), + siblings_height = 0, + available_height = 0; + + if ($siblings.length > 0 ) { + $siblings.each(function() { + siblings_height += $(this).outerHeight(true); + }); + } + available_height = parent_height - siblings_height; + if(available_height > el2spread_height ){ + $el2spread.outerHeight(available_height); + } +}; + +// Apply spreadHeight in html of discopower and consent +function resizeAll() { + // If there is an element with the particular selector, do the resizing + if($('.js-spread').length > 0) { + var $spread_els = $('.js-spread'); + $spread_els.each(function() { + spreadHeight($(this)); + }); + } +}; + +// Toggle error class to input parent div if empty +function handleMandatory(el) { + if ($(el).siblings('span.mandatory').length >0) { + if (el.val().trim().length === 0) { + el.parent('div').addClass('error-mandatory'); + } else { + el.parent('div').removeClass('error-mandatory'); + } + } +} + +// Toggle error class to input parent div if mail invalid +function handleMail(el) { + var regex = new RegExp(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i); + var res = regex.test(el.val().trim()); + if (!res) { + el.parent('div').addClass('error-mail'); + } else { + el.parent('div').removeClass('error-mail'); + } +} + +function handleTerms(el) { + if (el.is(':checked')) { + el.parent('div').removeClass('error-mandatory'); + } else { + el.parent('div').addClass('error-mandatory'); + } +} + +function getCookie(cname) { + var name = cname + "="; + var decodedCookie = decodeURIComponent(document.cookie); + var ca = decodedCookie.split(';'); + for(var i = 0; i 0; + if (!has_form) { + $('h2 small').hide(); + } + + + + $('[data-toggle="tooltip"]').tooltip(); + + resizeAll(); + // loader for discopower view + $('#loader').delay(300).fadeOut('slow', function() { + $('#loader').siblings().show(); + var setLang = getCookie('setLang'); + if (setLang) { + $('#edugain-modal').modal('show'); + deleteCookie('setLang'); + } else { + $('#favourite-modal').modal('show'); + } + }); + + // hide modal smoothly + $('.js-close-custom').click(function() { + $modal = $(this).closest('.modal.fade'); + $modal.slideUp(450, function() { + $modal.modal('hide'); + }); + }); + + $(window).resize(function() { + resizeAll(); + }); + + $('button[name="yes"]').click(function(e){ + var inputs = $('input.form-control'); + // Check if mandatory input field is empty + inputs.each(function(key, input) { + handleMandatory($(input)); + }); + // Check if mail field is properly formatted + var mailInputs = $('input[name="mail"]'); + mailInputs.each(function(key, input) { + handleMail($(input)); + }); + // If termsAccepted checkbox exists, check if the user has accepted terms + var termsInput = $('input[name="termsAccepted"]')[0]; + if (termsInput) { + handleTerms($(termsInput)); + } + + // Do not submit form if there are any errors + if (parseInt($('.error-mandatory').length) + parseInt($('.error-mail').length)>0) { + return false; + } + + // If the user has filled in inputs, show loader and fill hiden + // `userData` input with user data + if (inputs.length > 0) { + var data = {}; + inputs.each(function(key, input) { + var name = $(input).attr('name'); + var value = $(input).val().trim(); + data[name] = value; + }); + var mailRadio = $('input[type="radio"][name="mail"]:checked') + var hasMultiple = mailRadio.length > 0; + if (hasMultiple) { + data['mail'] = mailRadio.val(); + } + $('input[name="userData"]').val(JSON.stringify(data)); + $('#loader').show(); + + $('#loader').siblings().hide(); + } + + }) + + $('input.form-control').bind("keyup change", function(e) { + handleMandatory($(this)); + }) + + $('input[name="mail"]').bind("keyup change", function(e) { + handleMail($(this)); + }) + + $('input[name="termsAccepted"]').bind("keyup change", function(e) { + handleTerms($(this)); + }) + + $('#edugain-modal').on('shown.bs.modal', function(e) { + $('#query_edugain').liveUpdate('#list_edugain'); + }); + + $('.js-pick-language').click(function(e) { + e.preventDefault(); + setCookie('setLang', true) + window.location = $(this).attr('href'); + }); + +}); diff --git a/www/resources/js/tooltip.js b/www/resources/js/tooltip.js new file mode 100644 index 0000000..7094b34 --- /dev/null +++ b/www/resources/js/tooltip.js @@ -0,0 +1,514 @@ +/* ======================================================================== + * Bootstrap: tooltip.js v3.3.6 + * http://getbootstrap.com/javascript/#tooltip + * Inspired by the original jQuery.tipsy by Jason Frame + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // TOOLTIP PUBLIC CLASS DEFINITION + // =============================== + + var Tooltip = function (element, options) { + this.type = null + this.options = null + this.enabled = null + this.timeout = null + this.hoverState = null + this.$element = null + this.inState = null + + this.init('tooltip', element, options) + } + + Tooltip.VERSION = '3.3.6' + + Tooltip.TRANSITION_DURATION = 150 + + Tooltip.DEFAULTS = { + animation: true, + placement: 'top', + selector: false, + template: '', + trigger: 'hover focus', + title: '', + delay: 0, + html: false, + container: false, + viewport: { + selector: 'body', + padding: 0 + } + } + + Tooltip.prototype.init = function (type, element, options) { + this.enabled = true + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) + this.inState = { click: false, hover: false, focus: false } + + if (this.$element[0] instanceof document.constructor && !this.options.selector) { + throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') + } + + var triggers = this.options.trigger.split(' ') + + for (var i = triggers.length; i--;) { + var trigger = triggers[i] + + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' + var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' + + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + Tooltip.prototype.getDefaults = function () { + return Tooltip.DEFAULTS + } + + Tooltip.prototype.getOptions = function (options) { + options = $.extend({}, this.getDefaults(), this.$element.data(), options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay, + hide: options.delay + } + } + + return options + } + + Tooltip.prototype.getDelegateOptions = function () { + var options = {} + var defaults = this.getDefaults() + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] != value) options[key] = value + }) + + return options + } + + Tooltip.prototype.enter = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true + } + + if (self.tip().hasClass('in') || self.hoverState == 'in') { + self.hoverState = 'in' + return + } + + clearTimeout(self.timeout) + + self.hoverState = 'in' + + if (!self.options.delay || !self.options.delay.show) return self.show() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + Tooltip.prototype.isInStateTrue = function () { + for (var key in this.inState) { + if (this.inState[key]) return true + } + + return false + } + + Tooltip.prototype.leave = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false + } + + if (self.isInStateTrue()) return + + clearTimeout(self.timeout) + + self.hoverState = 'out' + + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + Tooltip.prototype.show = function () { + var e = $.Event('show.bs.' + this.type) + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) + if (e.isDefaultPrevented() || !inDom) return + var that = this + + var $tip = this.tip() + + var tipId = this.getUID(this.type) + + this.setContent() + $tip.attr('id', tipId) + this.$element.attr('aria-describedby', tipId) + + if (this.options.animation) $tip.addClass('fade') + + var placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + var autoToken = /\s?auto?\s?/i + var autoPlace = autoToken.test(placement) + if (autoPlace) placement = placement.replace(autoToken, '') || 'top' + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .addClass(placement) + .data('bs.' + this.type, this) + + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + this.$element.trigger('inserted.bs.' + this.type) + + var pos = this.getPosition() + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (autoPlace) { + var orgPlacement = placement + var viewportDim = this.getPosition(this.$viewport) + + placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : + placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : + placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : + placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : + placement + + $tip + .removeClass(orgPlacement) + .addClass(placement) + } + + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) + + this.applyPlacement(calculatedOffset, placement) + + var complete = function () { + var prevHoverState = that.hoverState + that.$element.trigger('shown.bs.' + that.type) + that.hoverState = null + + if (prevHoverState == 'out') that.leave(that) + } + + $.support.transition && this.$tip.hasClass('fade') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + } + } + + Tooltip.prototype.applyPlacement = function (offset, placement) { + var $tip = this.tip() + var width = $tip[0].offsetWidth + var height = $tip[0].offsetHeight + + // manually read margins because getBoundingClientRect includes difference + var marginTop = parseInt($tip.css('margin-top'), 10) + var marginLeft = parseInt($tip.css('margin-left'), 10) + + // we must check for NaN for ie 8/9 + if (isNaN(marginTop)) marginTop = 0 + if (isNaN(marginLeft)) marginLeft = 0 + + offset.top += marginTop + offset.left += marginLeft + + // $.fn.offset doesn't round pixel values + // so we use setOffset directly with our own function B-0 + $.offset.setOffset($tip[0], $.extend({ + using: function (props) { + $tip.css({ + top: Math.round(props.top), + left: Math.round(props.left) + }) + } + }, offset), 0) + + $tip.addClass('in') + + // check to see if placing tip in new offset caused the tip to resize itself + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + } + + var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) + + if (delta.left) offset.left += delta.left + else offset.top += delta.top + + var isVertical = /top|bottom/.test(placement) + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' + + $tip.offset(offset) + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) + } + + Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { + this.arrow() + .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') + .css(isVertical ? 'top' : 'left', '') + } + + Tooltip.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + + $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) + $tip.removeClass('fade in top bottom left right') + } + + Tooltip.prototype.hide = function (callback) { + var that = this + var $tip = $(this.$tip) + var e = $.Event('hide.bs.' + this.type) + + function complete() { + if (that.hoverState != 'in') $tip.detach() + that.$element + .removeAttr('aria-describedby') + .trigger('hidden.bs.' + that.type) + callback && callback() + } + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + $tip.removeClass('in') + + $.support.transition && $tip.hasClass('fade') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + + this.hoverState = null + + return this + } + + Tooltip.prototype.fixTitle = function () { + var $e = this.$element + if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') + } + } + + Tooltip.prototype.hasContent = function () { + return this.getTitle() + } + + Tooltip.prototype.getPosition = function ($element) { + $element = $element || this.$element + + var el = $element[0] + var isBody = el.tagName == 'BODY' + + var elRect = el.getBoundingClientRect() + if (elRect.width == null) { + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) + } + var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null + + return $.extend({}, elRect, scroll, outerDims, elOffset) + } + + Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } + + } + + Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { + var delta = { top: 0, left: 0 } + if (!this.$viewport) return delta + + var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 + var viewportDimensions = this.getPosition(this.$viewport) + + if (/right|left/.test(placement)) { + var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll + var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight + if (topEdgeOffset < viewportDimensions.top) { // top overflow + delta.top = viewportDimensions.top - topEdgeOffset + } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow + delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset + } + } else { + var leftEdgeOffset = pos.left - viewportPadding + var rightEdgeOffset = pos.left + viewportPadding + actualWidth + if (leftEdgeOffset < viewportDimensions.left) { // left overflow + delta.left = viewportDimensions.left - leftEdgeOffset + } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow + delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset + } + } + + return delta + } + + Tooltip.prototype.getTitle = function () { + var title + var $e = this.$element + var o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + Tooltip.prototype.getUID = function (prefix) { + do prefix += ~~(Math.random() * 1000000) + while (document.getElementById(prefix)) + return prefix + } + + Tooltip.prototype.tip = function () { + if (!this.$tip) { + this.$tip = $(this.options.template) + if (this.$tip.length != 1) { + throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') + } + } + return this.$tip + } + + Tooltip.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) + } + + Tooltip.prototype.enable = function () { + this.enabled = true + } + + Tooltip.prototype.disable = function () { + this.enabled = false + } + + Tooltip.prototype.toggleEnabled = function () { + this.enabled = !this.enabled + } + + Tooltip.prototype.toggle = function (e) { + var self = this + if (e) { + self = $(e.currentTarget).data('bs.' + this.type) + if (!self) { + self = new this.constructor(e.currentTarget, this.getDelegateOptions()) + $(e.currentTarget).data('bs.' + this.type, self) + } + } + + if (e) { + self.inState.click = !self.inState.click + if (self.isInStateTrue()) self.enter(self) + else self.leave(self) + } else { + self.tip().hasClass('in') ? self.leave(self) : self.enter(self) + } + } + + Tooltip.prototype.destroy = function () { + var that = this + clearTimeout(this.timeout) + this.hide(function () { + that.$element.off('.' + that.type).removeData('bs.' + that.type) + if (that.$tip) { + that.$tip.detach() + } + that.$tip = null + that.$arrow = null + that.$viewport = null + }) + } + + + // TOOLTIP PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tooltip') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tooltip + + $.fn.tooltip = Plugin + $.fn.tooltip.Constructor = Tooltip + + + // TOOLTIP NO CONFLICT + // =================== + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(jQuery); diff --git a/www/resources/sass/_bootstrap-custom.scss b/www/resources/sass/_bootstrap-custom.scss new file mode 100644 index 0000000..5cb3df5 --- /dev/null +++ b/www/resources/sass/_bootstrap-custom.scss @@ -0,0 +1,56 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +// Core variables and mixins +@import "bootstrap/variables"; +@import "bootstrap/mixins"; + +// Reset and dependencies +@import "bootstrap/normalize"; +@import "bootstrap/print"; +@import "bootstrap/glyphicons"; + +// Core CSS +@import "bootstrap/scaffolding"; +@import "bootstrap/type"; +@import "bootstrap/code"; +@import "bootstrap/grid"; +@import "bootstrap/tables"; +@import "bootstrap/forms"; +@import "bootstrap/buttons"; + +// Components +// @import "bootstrap/component-animations"; +@import "bootstrap/dropdowns"; +// @import "bootstrap/button-groups"; +@import "bootstrap/input-groups"; +// @import "bootstrap/navs"; +// @import "bootstrap/navbar"; +// @import "bootstrap/breadcrumbs"; +// @import "bootstrap/pagination"; +// @import "bootstrap/pager"; +// @import "bootstrap/labels"; +// @import "bootstrap/badges"; +// @import "bootstrap/jumbotron"; +// @import "bootstrap/thumbnails"; +// @import "bootstrap/alerts"; +// @import "bootstrap/progress-bars"; +// @import "bootstrap/media"; +// @import "bootstrap/list-group"; +@import "bootstrap/panels"; +// @import "bootstrap/responsive-embed"; +// @import "bootstrap/wells"; +@import "bootstrap/close"; + +// Components w/ JavaScript +@import "bootstrap/modals"; +@import "bootstrap/tooltip"; +// @import "bootstrap/popovers"; +// @import "bootstrap/carousel"; + +// Utility classes +// @import "bootstrap/utilities"; +// @import "bootstrap/responsive-utilities"; diff --git a/www/resources/sass/_extra.scss b/www/resources/sass/_extra.scss new file mode 100644 index 0000000..10d7c48 --- /dev/null +++ b/www/resources/sass/_extra.scss @@ -0,0 +1,479 @@ +/* + * Naming conventions: BEM with prefix "b" (b comes from bem). + * Using this method can also separate the custom css rules from bootstrap's + * rules. + * Form: + * block--modifier__element + + */ +@import url('https://fonts.googleapis.com/css?family=Lato:400,300,300i'); +@import url('https://fonts.googleapis.com/css?family=Raleway|Raleway+Dots'); +@import url('https://fonts.googleapis.com/css?family=Roboto:300,400|Roboto+Condensed:300,400,700|Open+Sans:300, 600'); +$lato : 'Lato', serif; +$openSans: 'Open Sans', sans-serif; +$raleway: 'Raleway', sans-serif; +$roboto: 'Roboto', sans-serif; + +// Overall + +.font-smooth { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing:grayscale; +} + +body { + width: 100%; + margin: 0; + display: flex; + min-height: 100vh; + flex-direction: column; + +} + +.ssp-container { + flex: 1; +} + +.header, .ssp-footer { + flex: none; +} + +a { + border: 1px solid transparent; + @extend .font-smooth; + &:hover, &:active, &:focus { + color: $link-color-hover; + text-decoration: none; + } +} +*:focus { + outline: none !important; + border:1px solid $silver !important; + box-shadow: 0 0 10px $btn-action !important; +} + +form { + margin: 0; +} + +.ssp-text-left { + text-align: left!important; +} + + +// Headings +// No use of bem, when we want to override every instance of them + +$header-font-weight: 300; +$headers_margin_top: 50px; +.ssp-logo { + margin-top: $headers_margin_top; + a { + display: inline-block; + padding: 10px; + &:hover { + text-decoration: none; + } + } + img { + width: $logo-width; + } +} + +.headers-text { + font-weight: $header-font-weight; + font-family: $lato; + margin-top: $headers_margin_top; +} + +h1 { + @extend .headers-text; + font-size: 36px; + text-transform: none!important; + margin: 0; + &.disco { + color: $alt-text; + font-family: $openSans; + } +} + + +h1 small { + display: block; + font-size: 14px; + line-height: 1.4; + color: #ccc; + text-transform: none; + letter-spacing: 0; + font-style: italic; + margin-top: 10px; +} + +h2 { + @extend .headers-text; + font-size: 18px; + text-transform: none!important; +} + +h3 { + @extend .headers-text; + font-size: 16px; + &.disco { + @extend .font-smooth; + font-family: $raleway; + color: $light-gray; + margin-top: 20px; + } +} + +h4 { + @extend .headers-text; + font-size: 14px; +} + +h5, h6 { + @extend .headers-text; +} + +h2.subtle { + small { + color: #ccc; + display: block; + font-size: 14px; + margin-top: 10px; + } +} + +// Bottom + +.ssp-footer { + @extend .font-smooth; + background: $footer-bg; + color: $footer-text; + font-weight: 300; + &--container { + padding: 16px; + } +} + +.ssp-lang-container { + display: inline-block; + // position: absolute; + // bottom: -10px; + // right: 24px; +} + + +// Buttons + +$margin-btn: 20px; +$btn-distance: 10px; +$btn-img-height: 36px; +$btn-img-copy-height: 20px; +.ssp-btn { + @extend .font-smooth; + border-radius: 2px; + letter-spacing: 1px; + font-size: 13px; + padding: 15px; + line-height: 40px; + box-shadow: 0 3px 12px rgba(0,0,0,0.07); + border: 0 none; + margin-bottom: $margin-btn; + white-space: normal; + color: $scorpion; + font-family: $roboto; + &:hover, &:focus, &:active { + color: $btn-action; + box-shadow: 0 6px 50px rgba(0,0,0,0.05); + } + .caret { + margin-left: 12px; + } + @at-root &__lg { + width: 100%; + margin: 0; + } + @at-root &__action { + &:focus, &:active, &:hover { + color: $btn-action; + } + } + @at-root &__secondary { + &:focus, &:active, &:hover { + color: $mouse; + } + } + @at-root &__warning { + color: $btn-warning; + } + @at-root &__lg { + img { + height: $btn-img-height; + margin-right: $btn-distance; + &.round { + border-radius: $btn-img-height/2; + } + } + } + @at-root &__footer { + background-color: transparent; + color: $btn-footer; + border-color: transparent; + &:focus, &:active, &:hover { + color: $link-color-hover; + border-color: $silver; + } + } + &--round-icon { + padding: 0; + display: inline-block; + margin-top: $btn-distance/2; + margin-bottom: $btn-distance/2; + border-radius: $btn-img-height/2; + &:not(:last-child) { + margin-right: $btn-distance*2; + } + img { + height: $btn-img-height; + border-radius: $btn-img-height/2; + } + } + &--horizontal-icon { + padding: 6px 34px; + img { + height: $btn-img-height; + } + } + &--copy { + img { + height: $btn-img-copy-height; + } + } +} + +.ssp-btns-container { + text-align: center; + @at-root &--btn__right.ssp-btn { + margin-left: $btn-distance; + } + @at-root &--btn__left.ssp-btn { + margin-right: $btn-distance; + } +} + + +.ssp-dropdown__two_cols { + width: 320px; + padding: 6px; + @at-root &--item { + width: 50%; + float: left; + display: inline-block; + height: 30px; + } +} + +.ssp-btn__show-more { + color: $text-color; + &:hover { + color: $jacksons-purple; + } + +} + +// Content + +.ssp-content-group { + margin-bottom: 18px; + margin-top: 18px; + &__provider-list { + overflow: auto; + &--edugain { + padding: 6px 6px 6px 42px; + height: 400px; + a { + display: block; + position: relative; + padding: 4px 12px; + &:hover { + background-color: $alabaster; + } + } + } + &--other { + a { + display: inline-block; + position: relative; + padding: 0; + } + } + &--local { + padding: 2px 6px 2px 54px; + a { + display: inline-block; + position: relative; + } + } + } +} + +.ssp-attrs--container { + padding: 16px; + margin-bottom: 32px; +} + +.ssp-table { + margin-bottom: 0; + font-size: 13px; + @at-root &--tr__odd { + background-color: lighten($alabaster, 1%); + } + @at-root &--attrname { + width: 35%; + overflow: hidden; + float: left; + word-break: break-word; + text-align: right; + padding-right: 20px; + font-weight: bold; + } + @at-root &--attrvalue { + overflow: hidden; + word-break: break-word; + @at-root &--list--item { + border-bottom: 1px solid $gray-lighter; + padding: 6px 0; + } + } +} + +.ssp-or { + @extend .font-smooth; + font-family: $raleway; + font-size: 16px; + color: $manatee; + margin-top: 40px; + margin-bottom: 40px; +} + +body .ssp-modal-body { + padding: 30px; +} + +.ssp-error-code { + padding: 18px; + white-space: pre-line; +} + +.form-control ~span { + color: $state-danger-text; + font-size: 13px; + display: none; +} + +.error-mandatory input, +.error-mail input { + border-color: $alert-danger-text; +} + +.error-mandatory span.mandatory { + display: block; +} + +.error-mail span.mail { + display: block; +} + +input.form-control[type="radio"], input.form-control[type="checkbox"] { + margin: 4px 8px; + width: auto; + display: inline-block; + height: auto; + border: 0 none; +} + +.ssp-form--hint { + color: #989393; +} + +@keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Firefox < 16 */ +@-moz-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Safari, Chrome and Opera > 12.1 */ +@-webkit-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Internet Explorer */ +@-ms-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Opera < 12.1 */ +@-o-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + + .modal.fade .modal-dialog { +// When fading in the modal, animate it to slide down + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); // IE9 only + transform: translate(0, 0); +} + .modal.fade.in .modal-dialog { + -webkit-animation: fadein 0.5s; /* Safari, Chrome and Opera > 12.1 */ + -moz-animation: fadein 0.5s; /* Firefox < 16 */ + -ms-animation: fadein 0.5s; /* Internet Explorer */ + -o-animation: fadein 0.5s; /* Opera < 12.1 */ + animation: fadein 0.5s; + } + + .container { + // max-width: 375px; + } + + .ssp-link-forgot { + @extend .font-smooth; + &.pull-right { + float: right; + } + &.pull-left { + float: left; + } + } + + .ssp-btn__login { + margin-top: 18px; + } + + .ssp-container-small { + max-width: 280px; + margin: 0 auto; + } + + .ssp-signup { + @extend .font-smooth; + padding: 6px; + color: $text-color; + font-size: 15px; + a { + color: $link-color; + &:hover { + color: $link-color-hover; + } + } + + + } diff --git a/www/resources/sass/_loader.scss b/www/resources/sass/_loader.scss new file mode 100644 index 0000000..584230d --- /dev/null +++ b/www/resources/sass/_loader.scss @@ -0,0 +1,136 @@ +// Loader from http://tobiasahlin.com/spinkit/ + +#loader { + position: absolute; + width: 100%; + height: 100%; + // background: $mouse; + background: $white; + z-index: 10; + display: flex; + align-items: center; + justify-content: center; +} + +.sk-circle { + margin: 100px auto; + width: 100px; + height: 100px; + position: relative; +} +.sk-circle .sk-child { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; +} +.sk-circle .sk-child:before { + content: ''; + display: block; + margin: 0 auto; + width: 15%; + height: 15%; + background-color: $btn-action; + border-radius: 100%; + -webkit-animation: sk-circleBounceDelay 1.2s infinite ease-in-out both; + animation: sk-circleBounceDelay 1.2s infinite ease-in-out both; +} +.sk-circle .sk-circle2 { + -webkit-transform: rotate(30deg); + -ms-transform: rotate(30deg); + transform: rotate(30deg); } +.sk-circle .sk-circle3 { + -webkit-transform: rotate(60deg); + -ms-transform: rotate(60deg); + transform: rotate(60deg); } +.sk-circle .sk-circle4 { + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); } +.sk-circle .sk-circle5 { + -webkit-transform: rotate(120deg); + -ms-transform: rotate(120deg); + transform: rotate(120deg); } +.sk-circle .sk-circle6 { + -webkit-transform: rotate(150deg); + -ms-transform: rotate(150deg); + transform: rotate(150deg); } +.sk-circle .sk-circle7 { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); } +.sk-circle .sk-circle8 { + -webkit-transform: rotate(210deg); + -ms-transform: rotate(210deg); + transform: rotate(210deg); } +.sk-circle .sk-circle9 { + -webkit-transform: rotate(240deg); + -ms-transform: rotate(240deg); + transform: rotate(240deg); } +.sk-circle .sk-circle10 { + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); } +.sk-circle .sk-circle11 { + -webkit-transform: rotate(300deg); + -ms-transform: rotate(300deg); + transform: rotate(300deg); } +.sk-circle .sk-circle12 { + -webkit-transform: rotate(330deg); + -ms-transform: rotate(330deg); + transform: rotate(330deg); } +.sk-circle .sk-circle2:before { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; } +.sk-circle .sk-circle3:before { + -webkit-animation-delay: -1s; + animation-delay: -1s; } +.sk-circle .sk-circle4:before { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; } +.sk-circle .sk-circle5:before { + -webkit-animation-delay: -0.8s; + animation-delay: -0.8s; } +.sk-circle .sk-circle6:before { + -webkit-animation-delay: -0.7s; + animation-delay: -0.7s; } +.sk-circle .sk-circle7:before { + -webkit-animation-delay: -0.6s; + animation-delay: -0.6s; } +.sk-circle .sk-circle8:before { + -webkit-animation-delay: -0.5s; + animation-delay: -0.5s; } +.sk-circle .sk-circle9:before { + -webkit-animation-delay: -0.4s; + animation-delay: -0.4s; } +.sk-circle .sk-circle10:before { + -webkit-animation-delay: -0.3s; + animation-delay: -0.3s; } +.sk-circle .sk-circle11:before { + -webkit-animation-delay: -0.2s; + animation-delay: -0.2s; } +.sk-circle .sk-circle12:before { + -webkit-animation-delay: -0.1s; + animation-delay: -0.1s; } + +@-webkit-keyframes sk-circleBounceDelay { + 0%, 80%, 100% { + -webkit-transform: scale(0); + transform: scale(0); + } 40% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes sk-circleBounceDelay { + 0%, 80%, 100% { + -webkit-transform: scale(0); + transform: scale(0); + } 40% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + diff --git a/www/resources/sass/_settings.scss b/www/resources/sass/_settings.scss new file mode 100644 index 0000000..23c2335 --- /dev/null +++ b/www/resources/sass/_settings.scss @@ -0,0 +1,28 @@ +// Colors +// Color names from: http://chir.ag/projects/name-that-color + +$tradewind: #68b8b3; //green blue +$white: #fff; +$black: #333; +$denim: #0d6fcc; +$mariner: #2d72d6; +$punch: #d53b23; +$jacksons-purple: #232080; +$cerulean: #00a0de; +$blue-marine: #040067; +// Gray +$alabaster: #f7f7f7; +$silver: #cdc9c9; +$scorpion: #5b5b5b;; +$manatee: #90929D; +$mouse: #848484; +$light-gray: #767779; + +// Bootstrap variables +$link-color: $mariner; +$table-border-color: transparent; +$container-lg: 970px; + +// tooltip colors +$tooltip-bg: $tradewind; +$tooltip-color: $white; diff --git a/www/resources/sass/_settings_custom.scss b/www/resources/sass/_settings_custom.scss new file mode 100644 index 0000000..7098a01 --- /dev/null +++ b/www/resources/sass/_settings_custom.scss @@ -0,0 +1,15 @@ +// background color of primary button +$btn-action: $cerulean; +$btn-warning: $punch; +$footer-bg: $white; +$footer-text: #333; +$headers-color: $scorpion; +$link-color-hover: $cerulean; +// text and border color of button that is in the footer +$btn-footer: #333; + +$logo-height: 65px; +$logo-width: 200px; + +// h1 font color +$alt-text: $blue-marine; diff --git a/www/resources/sass/app.scss b/www/resources/sass/app.scss new file mode 100644 index 0000000..cdc7188 --- /dev/null +++ b/www/resources/sass/app.scss @@ -0,0 +1,5 @@ +@import "settings"; +@import "settings_custom"; +@import "bootstrap-custom"; +@import "extra"; +@import "loader"; diff --git a/www/resources/sass/bootstrap/_alerts.scss b/www/resources/sass/bootstrap/_alerts.scss new file mode 100644 index 0000000..7d1e1fd --- /dev/null +++ b/www/resources/sass/bootstrap/_alerts.scss @@ -0,0 +1,73 @@ +// +// Alerts +// -------------------------------------------------- + + +// Base styles +// ------------------------- + +.alert { + padding: $alert-padding; + margin-bottom: $line-height-computed; + border: 1px solid transparent; + border-radius: $alert-border-radius; + + // Headings for larger alerts + h4 { + margin-top: 0; + // Specified for the h4 to prevent conflicts of changing $headings-color + color: inherit; + } + + // Provide class for links that match alerts + .alert-link { + font-weight: $alert-link-font-weight; + } + + // Improve alignment and spacing of inner content + > p, + > ul { + margin-bottom: 0; + } + + > p + p { + margin-top: 5px; + } +} + +// Dismissible alerts +// +// Expand the right padding and account for the close button's positioning. + +.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. +.alert-dismissible { + padding-right: ($alert-padding + 20); + + // Adjust close link position + .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; + } +} + +// Alternate styles +// +// Generate contextual modifier classes for colorizing the alert. + +.alert-success { + @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text); +} + +.alert-info { + @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text); +} + +.alert-warning { + @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text); +} + +.alert-danger { + @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text); +} diff --git a/www/resources/sass/bootstrap/_badges.scss b/www/resources/sass/bootstrap/_badges.scss new file mode 100644 index 0000000..70002e0 --- /dev/null +++ b/www/resources/sass/bootstrap/_badges.scss @@ -0,0 +1,68 @@ +// +// Badges +// -------------------------------------------------- + + +// Base class +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: $font-size-small; + font-weight: $badge-font-weight; + color: $badge-color; + line-height: $badge-line-height; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: $badge-bg; + border-radius: $badge-border-radius; + + // Empty badges collapse automatically (not available in IE8) + &:empty { + display: none; + } + + // Quick fix for badges in buttons + .btn & { + position: relative; + top: -1px; + } + + .btn-xs &, + .btn-group-xs > .btn & { + top: 0; + padding: 1px 5px; + } + + // [converter] extracted a& to a.badge + + // Account for badges in navs + .list-group-item.active > &, + .nav-pills > .active > a > & { + color: $badge-active-color; + background-color: $badge-active-bg; + } + + .list-group-item > & { + float: right; + } + + .list-group-item > & + & { + margin-right: 5px; + } + + .nav-pills > li > a > & { + margin-left: 3px; + } +} + +// Hover state, but only for links +a.badge { + &:hover, + &:focus { + color: $badge-link-hover-color; + text-decoration: none; + cursor: pointer; + } +} diff --git a/www/resources/sass/bootstrap/_breadcrumbs.scss b/www/resources/sass/bootstrap/_breadcrumbs.scss new file mode 100644 index 0000000..b61f0c7 --- /dev/null +++ b/www/resources/sass/bootstrap/_breadcrumbs.scss @@ -0,0 +1,28 @@ +// +// Breadcrumbs +// -------------------------------------------------- + + +.breadcrumb { + padding: $breadcrumb-padding-vertical $breadcrumb-padding-horizontal; + margin-bottom: $line-height-computed; + list-style: none; + background-color: $breadcrumb-bg; + border-radius: $border-radius-base; + + > li { + display: inline-block; + + + li:before { + // [converter] Workaround for https://github.com/sass/libsass/issues/1115 + $nbsp: "\00a0"; + content: "#{$breadcrumb-separator}#{$nbsp}"; // Unicode space added since inline-block means non-collapsing white-space + padding: 0 5px; + color: $breadcrumb-color; + } + } + + > .active { + color: $breadcrumb-active-color; + } +} diff --git a/www/resources/sass/bootstrap/_button-groups.scss b/www/resources/sass/bootstrap/_button-groups.scss new file mode 100644 index 0000000..4b385f5 --- /dev/null +++ b/www/resources/sass/bootstrap/_button-groups.scss @@ -0,0 +1,244 @@ +// +// Button groups +// -------------------------------------------------- + +// Make the div behave like a button +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; // match .btn alignment given font-size hack above + > .btn { + position: relative; + float: left; + // Bring the "active" button to the front + &:hover, + &:focus, + &:active, + &.active { + z-index: 2; + } + } +} + +// Prevent double borders when buttons are next to each other +.btn-group { + .btn + .btn, + .btn + .btn-group, + .btn-group + .btn, + .btn-group + .btn-group { + margin-left: -1px; + } +} + +// Optional: Group multiple button groups together for a toolbar +.btn-toolbar { + margin-left: -5px; // Offset the first child's margin + @include clearfix; + + .btn, + .btn-group, + .input-group { + float: left; + } + > .btn, + > .btn-group, + > .input-group { + margin-left: 5px; + } +} + +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match +.btn-group > .btn:first-child { + margin-left: 0; + &:not(:last-child):not(.dropdown-toggle) { + @include border-right-radius(0); + } +} +// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + @include border-left-radius(0); +} + +// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group) +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) { + > .btn:last-child, + > .dropdown-toggle { + @include border-right-radius(0); + } +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + @include border-left-radius(0); +} + +// On active and open, don't show outline +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + + +// Sizing +// +// Remix the default button sizing classes into new ones for easier manipulation. + +.btn-group-xs > .btn { @extend .btn-xs; } +.btn-group-sm > .btn { @extend .btn-sm; } +.btn-group-lg > .btn { @extend .btn-lg; } + + +// Split button dropdowns +// ---------------------- + +// Give the line between buttons some depth +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} + +// The clickable button for toggling the menu +// Remove the gradient and set the same inset shadow as the :active state +.btn-group.open .dropdown-toggle { + @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + + // Show no shadow for `.btn-link` since it has no other button styles. + &.btn-link { + @include box-shadow(none); + } +} + + +// Reposition the caret +.btn .caret { + margin-left: 0; +} +// Carets in other button sizes +.btn-lg .caret { + border-width: $caret-width-large $caret-width-large 0; + border-bottom-width: 0; +} +// Upside down carets for .dropup +.dropup .btn-lg .caret { + border-width: 0 $caret-width-large $caret-width-large; +} + + +// Vertical button groups +// ---------------------- + +.btn-group-vertical { + > .btn, + > .btn-group, + > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; + } + + // Clear floats so dropdown menus can be properly placed + > .btn-group { + @include clearfix; + > .btn { + float: none; + } + } + + > .btn + .btn, + > .btn + .btn-group, + > .btn-group + .btn, + > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; + } +} + +.btn-group-vertical > .btn { + &:not(:first-child):not(:last-child) { + border-radius: 0; + } + &:first-child:not(:last-child) { + @include border-top-radius($btn-border-radius-base); + @include border-bottom-radius(0); + } + &:last-child:not(:first-child) { + @include border-top-radius(0); + @include border-bottom-radius($btn-border-radius-base); + } +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) { + > .btn:last-child, + > .dropdown-toggle { + @include border-bottom-radius(0); + } +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + @include border-top-radius(0); +} + + +// Justified button groups +// ---------------------- + +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; + > .btn, + > .btn-group { + float: none; + display: table-cell; + width: 1%; + } + > .btn-group .btn { + width: 100%; + } + + > .btn-group .dropdown-menu { + left: auto; + } +} + + +// Checkbox and radio options +// +// In order to support the browser's form validation feedback, powered by the +// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use +// `display: none;` or `visibility: hidden;` as that also hides the popover. +// Simply visually hiding the inputs via `opacity` would leave them clickable in +// certain cases which is prevented by using `clip` and `pointer-events`. +// This way, we ensure a DOM element is visible to position the popover from. +// +// See https://github.com/twbs/bootstrap/pull/12794 and +// https://github.com/twbs/bootstrap/pull/14559 for more information. + +[data-toggle="buttons"] { + > .btn, + > .btn-group > .btn { + input[type="radio"], + input[type="checkbox"] { + position: absolute; + clip: rect(0,0,0,0); + pointer-events: none; + } + } +} diff --git a/www/resources/sass/bootstrap/_buttons.scss b/www/resources/sass/bootstrap/_buttons.scss new file mode 100644 index 0000000..6452b70 --- /dev/null +++ b/www/resources/sass/bootstrap/_buttons.scss @@ -0,0 +1,168 @@ +// +// Buttons +// -------------------------------------------------- + + +// Base styles +// -------------------------------------------------- + +.btn { + display: inline-block; + margin-bottom: 0; // For input.btn + font-weight: $btn-font-weight; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 + border: 1px solid transparent; + white-space: nowrap; + @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $btn-border-radius-base); + @include user-select(none); + + &, + &:active, + &.active { + &:focus, + &.focus { + @include tab-focus; + } + } + + &:hover, + &:focus, + &.focus { + color: $btn-default-color; + text-decoration: none; + } + + &:active, + &.active { + outline: 0; + background-image: none; + @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); + } + + &.disabled, + &[disabled], + fieldset[disabled] & { + cursor: $cursor-disabled; + @include opacity(.65); + @include box-shadow(none); + } + + // [converter] extracted a& to a.btn +} + +a.btn { + &.disabled, + fieldset[disabled] & { + pointer-events: none; // Future-proof disabling of clicks on `` elements + } +} + + +// Alternate buttons +// -------------------------------------------------- + +.btn-default { + @include button-variant($btn-default-color, $btn-default-bg, $btn-default-border); +} +.btn-primary { + @include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border); +} +// Success appears as green +.btn-success { + @include button-variant($btn-success-color, $btn-success-bg, $btn-success-border); +} +// Info appears as blue-green +.btn-info { + @include button-variant($btn-info-color, $btn-info-bg, $btn-info-border); +} +// Warning appears as orange +.btn-warning { + @include button-variant($btn-warning-color, $btn-warning-bg, $btn-warning-border); +} +// Danger and error appear as red +.btn-danger { + @include button-variant($btn-danger-color, $btn-danger-bg, $btn-danger-border); +} + + +// Link buttons +// ------------------------- + +// Make a button look and behave like a link +.btn-link { + color: $link-color; + font-weight: normal; + border-radius: 0; + + &, + &:active, + &.active, + &[disabled], + fieldset[disabled] & { + background-color: transparent; + @include box-shadow(none); + } + &, + &:hover, + &:focus, + &:active { + border-color: transparent; + } + &:hover, + &:focus { + color: $link-hover-color; + text-decoration: $link-hover-decoration; + background-color: transparent; + } + &[disabled], + fieldset[disabled] & { + &:hover, + &:focus { + color: $btn-link-disabled-color; + text-decoration: none; + } + } +} + + +// Button Sizes +// -------------------------------------------------- + +.btn-lg { + // line-height: ensure even-numbered height of button next to large input + @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $btn-border-radius-large); +} +.btn-sm { + // line-height: ensure proper height of button next to small input + @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $btn-border-radius-small); +} +.btn-xs { + @include button-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $line-height-small, $btn-border-radius-small); +} + + +// Block button +// -------------------------------------------------- + +.btn-block { + display: block; + width: 100%; +} + +// Vertically space out multiple block buttons +.btn-block + .btn-block { + margin-top: 5px; +} + +// Specificity overrides +input[type="submit"], +input[type="reset"], +input[type="button"] { + &.btn-block { + width: 100%; + } +} diff --git a/www/resources/sass/bootstrap/_carousel.scss b/www/resources/sass/bootstrap/_carousel.scss new file mode 100644 index 0000000..753d881 --- /dev/null +++ b/www/resources/sass/bootstrap/_carousel.scss @@ -0,0 +1,270 @@ +// +// Carousel +// -------------------------------------------------- + + +// Wrapper for the slide container and indicators +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; + + > .item { + display: none; + position: relative; + @include transition(.6s ease-in-out left); + + // Account for jankitude on images + > img, + > a > img { + @include img-responsive; + line-height: 1; + } + + // WebKit CSS3 transforms for supported devices + @media all and (transform-3d), (-webkit-transform-3d) { + @include transition-transform(0.6s ease-in-out); + @include backface-visibility(hidden); + @include perspective(1000px); + + &.next, + &.active.right { + @include translate3d(100%, 0, 0); + left: 0; + } + &.prev, + &.active.left { + @include translate3d(-100%, 0, 0); + left: 0; + } + &.next.left, + &.prev.right, + &.active { + @include translate3d(0, 0, 0); + left: 0; + } + } + } + + > .active, + > .next, + > .prev { + display: block; + } + + > .active { + left: 0; + } + + > .next, + > .prev { + position: absolute; + top: 0; + width: 100%; + } + + > .next { + left: 100%; + } + > .prev { + left: -100%; + } + > .next.left, + > .prev.right { + left: 0; + } + + > .active.left { + left: -100%; + } + > .active.right { + left: 100%; + } + +} + +// Left/right controls for nav +// --------------------------- + +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: $carousel-control-width; + @include opacity($carousel-control-opacity); + font-size: $carousel-control-font-size; + color: $carousel-control-color; + text-align: center; + text-shadow: $carousel-text-shadow; + background-color: rgba(0, 0, 0, 0); // Fix IE9 click-thru bug + // We can't have this transition here because WebKit cancels the carousel + // animation if you trip this while in the middle of another animation. + + // Set gradients for backgrounds + &.left { + @include gradient-horizontal($start-color: rgba(0,0,0,.5), $end-color: rgba(0,0,0,.0001)); + } + &.right { + left: auto; + right: 0; + @include gradient-horizontal($start-color: rgba(0,0,0,.0001), $end-color: rgba(0,0,0,.5)); + } + + // Hover/focus state + &:hover, + &:focus { + outline: 0; + color: $carousel-control-color; + text-decoration: none; + @include opacity(.9); + } + + // Toggles + .icon-prev, + .icon-next, + .glyphicon-chevron-left, + .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; + } + .icon-prev, + .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; + } + .icon-next, + .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; + } + .icon-prev, + .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; + } + + + .icon-prev { + &:before { + content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) + } + } + .icon-next { + &:before { + content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) + } + } +} + +// Optional indicator pips +// +// Add an unordered list with the following class and add a list item for each +// slide your carousel holds. + +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; + + li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid $carousel-indicator-border-color; + border-radius: 10px; + cursor: pointer; + + // IE8-9 hack for event handling + // + // Internet Explorer 8-9 does not support clicks on elements without a set + // `background-color`. We cannot use `filter` since that's not viewed as a + // background color by the browser. Thus, a hack is needed. + // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer + // + // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we + // set alpha transparency for the best results possible. + background-color: #000 \9; // IE8 + background-color: rgba(0,0,0,0); // IE9 + } + .active { + margin: 0; + width: 12px; + height: 12px; + background-color: $carousel-indicator-active-bg; + } +} + +// Optional captions +// ----------------------------- +// Hidden by default for smaller viewports +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: $carousel-caption-color; + text-align: center; + text-shadow: $carousel-text-shadow; + & .btn { + text-shadow: none; // No shadow for button elements in carousel-caption + } +} + + +// Scale up controls for tablets and up +@media screen and (min-width: $screen-sm-min) { + + // Scale up the controls a smidge + .carousel-control { + .glyphicon-chevron-left, + .glyphicon-chevron-right, + .icon-prev, + .icon-next { + width: ($carousel-control-font-size * 1.5); + height: ($carousel-control-font-size * 1.5); + margin-top: ($carousel-control-font-size / -2); + font-size: ($carousel-control-font-size * 1.5); + } + .glyphicon-chevron-left, + .icon-prev { + margin-left: ($carousel-control-font-size / -2); + } + .glyphicon-chevron-right, + .icon-next { + margin-right: ($carousel-control-font-size / -2); + } + } + + // Show and left align the captions + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + + // Move up the indicators + .carousel-indicators { + bottom: 20px; + } +} diff --git a/www/resources/sass/bootstrap/_close.scss b/www/resources/sass/bootstrap/_close.scss new file mode 100644 index 0000000..3b74d8a --- /dev/null +++ b/www/resources/sass/bootstrap/_close.scss @@ -0,0 +1,36 @@ +// +// Close icons +// -------------------------------------------------- + + +.close { + float: right; + font-size: ($font-size-base * 1.5); + font-weight: $close-font-weight; + line-height: 1; + color: $close-color; + text-shadow: $close-text-shadow; + @include opacity(.2); + + &:hover, + &:focus { + color: $close-color; + text-decoration: none; + cursor: pointer; + @include opacity(.5); + } + + // [converter] extracted button& to button.close +} + +// Additional properties for button version +// iOS requires the button element instead of an anchor tag. +// If you want the anchor version, it requires `href="#"`. +// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} diff --git a/www/resources/sass/bootstrap/_code.scss b/www/resources/sass/bootstrap/_code.scss new file mode 100644 index 0000000..caa5f06 --- /dev/null +++ b/www/resources/sass/bootstrap/_code.scss @@ -0,0 +1,69 @@ +// +// Code (inline and block) +// -------------------------------------------------- + + +// Inline and block code styles +code, +kbd, +pre, +samp { + font-family: $font-family-monospace; +} + +// Inline code +code { + padding: 2px 4px; + font-size: 90%; + color: $code-color; + background-color: $code-bg; + border-radius: $border-radius-base; +} + +// User input typically entered via keyboard +kbd { + padding: 2px 4px; + font-size: 90%; + color: $kbd-color; + background-color: $kbd-bg; + border-radius: $border-radius-small; + box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); + + kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; + } +} + +// Blocks of code +pre { + display: block; + padding: (($line-height-computed - 1) / 2); + margin: 0 0 ($line-height-computed / 2); + font-size: ($font-size-base - 1); // 14px to 13px + line-height: $line-height-base; + word-break: break-all; + word-wrap: break-word; + color: $pre-color; + background-color: $pre-bg; + border: 1px solid $pre-border-color; + border-radius: $border-radius-base; + + // Account for some code outputs that place code tags in pre tags + code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; + } +} + +// Enable scrollable blocks of code +.pre-scrollable { + max-height: $pre-scrollable-max-height; + overflow-y: scroll; +} diff --git a/www/resources/sass/bootstrap/_component-animations.scss b/www/resources/sass/bootstrap/_component-animations.scss new file mode 100644 index 0000000..ca3b43c --- /dev/null +++ b/www/resources/sass/bootstrap/_component-animations.scss @@ -0,0 +1,37 @@ +// +// Component animations +// -------------------------------------------------- + +// Heads up! +// +// We don't use the `.opacity()` mixin here since it causes a bug with text +// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552. + +.fade { + opacity: 0; + @include transition(opacity .15s linear); + &.in { + opacity: 1; + } +} + +.collapse { + display: none; + + &.in { display: block; } + // [converter] extracted tr&.in to tr.collapse.in + // [converter] extracted tbody&.in to tbody.collapse.in +} + +tr.collapse.in { display: table-row; } + +tbody.collapse.in { display: table-row-group; } + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + @include transition-property(height, visibility); + @include transition-duration(.35s); + @include transition-timing-function(ease); +} diff --git a/www/resources/sass/bootstrap/_dropdowns.scss b/www/resources/sass/bootstrap/_dropdowns.scss new file mode 100644 index 0000000..aac8459 --- /dev/null +++ b/www/resources/sass/bootstrap/_dropdowns.scss @@ -0,0 +1,216 @@ +// +// Dropdown menus +// -------------------------------------------------- + + +// Dropdown arrow/caret +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: $caret-width-base dashed; + border-top: $caret-width-base solid \9; // IE8 + border-right: $caret-width-base solid transparent; + border-left: $caret-width-base solid transparent; +} + +// The dropdown wrapper (div) +.dropup, +.dropdown { + position: relative; +} + +// Prevent the focus on the dropdown toggle when closing dropdowns +.dropdown-toggle:focus { + outline: 0; +} + +// The dropdown menu (ul) +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: $zindex-dropdown; + display: none; // none by default, but block on "open" of the menu + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; // override default ul + list-style: none; + font-size: $font-size-base; + text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) + background-color: $dropdown-bg; + border: 1px solid $dropdown-fallback-border; // IE8 fallback + border: 1px solid $dropdown-border; + border-radius: $border-radius-base; + @include box-shadow(0 6px 12px rgba(0,0,0,.175)); + background-clip: padding-box; + + // Aligns the dropdown menu to right + // + // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]` + &.pull-right { + right: 0; + left: auto; + } + + // Dividers (basically an hr) within the dropdown + .divider { + @include nav-divider($dropdown-divider-bg); + } + + // Links within the dropdown menu + > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: $line-height-base; + color: $dropdown-link-color; + white-space: nowrap; // prevent links from randomly breaking onto new lines + } +} + +// Hover/Focus state +.dropdown-menu > li > a { + &:hover, + &:focus { + text-decoration: none; + color: $dropdown-link-hover-color; + background-color: $dropdown-link-hover-bg; + } +} + +// Active state +.dropdown-menu > .active > a { + &, + &:hover, + &:focus { + color: $dropdown-link-active-color; + text-decoration: none; + outline: 0; + background-color: $dropdown-link-active-bg; + } +} + +// Disabled state +// +// Gray out text and ensure the hover/focus state remains gray + +.dropdown-menu > .disabled > a { + &, + &:hover, + &:focus { + color: $dropdown-link-disabled-color; + } + + // Nuke hover/focus effects + &:hover, + &:focus { + text-decoration: none; + background-color: transparent; + background-image: none; // Remove CSS gradient + @include reset-filter; + cursor: $cursor-disabled; + } +} + +// Open state for the dropdown +.open { + // Show the menu + > .dropdown-menu { + display: block; + } + + // Remove the outline when :focus is triggered + > a { + outline: 0; + } +} + +// Menu positioning +// +// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown +// menu with the parent. +.dropdown-menu-right { + left: auto; // Reset the default from `.dropdown-menu` + right: 0; +} +// With v3, we enabled auto-flipping if you have a dropdown within a right +// aligned nav component. To enable the undoing of that, we provide an override +// to restore the default dropdown menu alignment. +// +// This is only for left-aligning a dropdown menu within a `.navbar-right` or +// `.pull-right` nav component. +.dropdown-menu-left { + left: 0; + right: auto; +} + +// Dropdown section headers +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: $font-size-small; + line-height: $line-height-base; + color: $dropdown-header-color; + white-space: nowrap; // as with > li > a +} + +// Backdrop to catch body clicks on mobile, etc. +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: ($zindex-dropdown - 10); +} + +// Right aligned dropdowns +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +// Allow for dropdowns to go bottom up (aka, dropup-menu) +// +// Just add .dropup after the standard .dropdown class and you're set, bro. +// TODO: abstract this so that the navbar fixed styles are not placed here? + +.dropup, +.navbar-fixed-bottom .dropdown { + // Reverse the caret + .caret { + border-top: 0; + border-bottom: $caret-width-base dashed; + border-bottom: $caret-width-base solid \9; // IE8 + content: ""; + } + // Different positioning for bottom up menu + .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; + } +} + + +// Component alignment +// +// Reiterate per navbar.less and the modified component alignment there. + +@media (min-width: $grid-float-breakpoint) { + .navbar-right { + .dropdown-menu { + right: 0; left: auto; + } + // Necessary for overrides of the default right aligned menu. + // Will remove come v4 in all likelihood. + .dropdown-menu-left { + left: 0; right: auto; + } + } +} diff --git a/www/resources/sass/bootstrap/_forms.scss b/www/resources/sass/bootstrap/_forms.scss new file mode 100644 index 0000000..ac26a6a --- /dev/null +++ b/www/resources/sass/bootstrap/_forms.scss @@ -0,0 +1,617 @@ +// +// Forms +// -------------------------------------------------- + + +// Normalize non-controls +// +// Restyle and baseline non-control form elements. + +fieldset { + padding: 0; + margin: 0; + border: 0; + // Chrome and Firefox set a `min-width: min-content;` on fieldsets, + // so we reset that to ensure it behaves more like a standard block element. + // See https://github.com/twbs/bootstrap/issues/12359. + min-width: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: $line-height-computed; + font-size: ($font-size-base * 1.5); + line-height: inherit; + color: $legend-color; + border: 0; + border-bottom: 1px solid $legend-border-color; +} + +label { + display: inline-block; + max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141) + margin-bottom: 5px; + font-weight: bold; +} + + +// Normalize form controls +// +// While most of our form styles require extra classes, some basic normalization +// is required to ensure optimum display with or without those classes to better +// address browser inconsistencies. + +// Override content-box in Normalize (* isn't specific enough) +input[type="search"] { + @include box-sizing(border-box); +} + +// Position radios and checkboxes better +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; // IE8-9 + line-height: normal; +} + +input[type="file"] { + display: block; +} + +// Make range inputs behave like textual form controls +input[type="range"] { + display: block; + width: 100%; +} + +// Make multiple select elements height not fixed +select[multiple], +select[size] { + height: auto; +} + +// Focus for file, radio, and checkbox +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + @include tab-focus; +} + +// Adjust output element +output { + display: block; + padding-top: ($padding-base-vertical + 1); + font-size: $font-size-base; + line-height: $line-height-base; + color: $input-color; +} + + +// Common form controls +// +// Shared size and type resets for form controls. Apply `.form-control` to any +// of the following form controls: +// +// select +// textarea +// input[type="text"] +// input[type="password"] +// input[type="datetime"] +// input[type="datetime-local"] +// input[type="date"] +// input[type="month"] +// input[type="time"] +// input[type="week"] +// input[type="number"] +// input[type="email"] +// input[type="url"] +// input[type="search"] +// input[type="tel"] +// input[type="color"] + +.form-control { + display: block; + width: 100%; + height: $input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border) + padding: $padding-base-vertical $padding-base-horizontal; + font-size: $font-size-base; + line-height: $line-height-base; + color: $input-color; + background-color: $input-bg; + background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 + border: 1px solid $input-border; + border-radius: $input-border-radius; // Note: This has no effect on s in CSS. + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); + @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s); + + // Customize the `:focus` state to imitate native WebKit styles. + @include form-control-focus; + + // Placeholder + @include placeholder; + + // Unstyle the caret on `` background color +$input-bg: #fff !default; +//** `` background color +$input-bg-disabled: $gray-lighter !default; + +//** Text color for ``s +$input-color: $gray !default; +//** `` border color +$input-border: #ccc !default; + +// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4 +//** Default `.form-control` border radius +// This has no effect on ``s in CSS. +$input-border-radius: $border-radius-base !default; +//** Large `.form-control` border radius +$input-border-radius-large: $border-radius-large !default; +//** Small `.form-control` border radius +$input-border-radius-small: $border-radius-small !default; + +//** Border color for inputs on focus +$input-border-focus: #66afe9 !default; + +//** Placeholder text color +$input-color-placeholder: #999 !default; + +//** Default `.form-control` height +$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) !default; +//** Large `.form-control` height +$input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default; +//** Small `.form-control` height +$input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default; + +//** `.form-group` margin +$form-group-margin-bottom: 15px !default; + +$legend-color: $gray-dark !default; +$legend-border-color: #e5e5e5 !default; + +//** Background color for textual input addons +$input-group-addon-bg: $gray-lighter !default; +//** Border color for textual input addons +$input-group-addon-border-color: $input-border !default; + +//** Disabled cursor for form controls and buttons. +$cursor-disabled: not-allowed !default; + + +//== Dropdowns +// +//## Dropdown menu container and contents. + +//** Background for the dropdown menu. +$dropdown-bg: #fff !default; +//** Dropdown menu `border-color`. +$dropdown-border: rgba(0,0,0,.15) !default; +//** Dropdown menu `border-color` **for IE8**. +$dropdown-fallback-border: #ccc !default; +//** Divider color for between dropdown items. +$dropdown-divider-bg: #e5e5e5 !default; + +//** Dropdown link text color. +$dropdown-link-color: $gray-dark !default; +//** Hover color for dropdown links. +$dropdown-link-hover-color: darken($gray-dark, 5%) !default; +//** Hover background for dropdown links. +$dropdown-link-hover-bg: #f5f5f5 !default; + +//** Active dropdown menu item text color. +$dropdown-link-active-color: $component-active-color !default; +//** Active dropdown menu item background color. +$dropdown-link-active-bg: $component-active-bg !default; + +//** Disabled dropdown menu item background color. +$dropdown-link-disabled-color: $gray-light !default; + +//** Text color for headers within dropdown menus. +$dropdown-header-color: $gray-light !default; + +//** Deprecated `$dropdown-caret-color` as of v3.1.0 +$dropdown-caret-color: #000 !default; + + +//-- Z-index master list +// +// Warning: Avoid customizing these values. They're used for a bird's eye view +// of components dependent on the z-axis and are designed to all work together. +// +// Note: These variables are not generated into the Customizer. + +$zindex-navbar: 1000 !default; +$zindex-dropdown: 1000 !default; +$zindex-popover: 1060 !default; +$zindex-tooltip: 1070 !default; +$zindex-navbar-fixed: 1030 !default; +$zindex-modal-background: 1040 !default; +$zindex-modal: 1050 !default; + + +//== Media queries breakpoints +// +//## Define the breakpoints at which your layout will change, adapting to different screen sizes. + +// Extra small screen / phone +//** Deprecated `$screen-xs` as of v3.0.1 +$screen-xs: 480px !default; +//** Deprecated `$screen-xs-min` as of v3.2.0 +$screen-xs-min: $screen-xs !default; +//** Deprecated `$screen-phone` as of v3.0.1 +$screen-phone: $screen-xs-min !default; + +// Small screen / tablet +//** Deprecated `$screen-sm` as of v3.0.1 +$screen-sm: 768px !default; +$screen-sm-min: $screen-sm !default; +//** Deprecated `$screen-tablet` as of v3.0.1 +$screen-tablet: $screen-sm-min !default; + +// Medium screen / desktop +//** Deprecated `$screen-md` as of v3.0.1 +$screen-md: 992px !default; +$screen-md-min: $screen-md !default; +//** Deprecated `$screen-desktop` as of v3.0.1 +$screen-desktop: $screen-md-min !default; + +// Large screen / wide desktop +//** Deprecated `$screen-lg` as of v3.0.1 +$screen-lg: 1200px !default; +$screen-lg-min: $screen-lg !default; +//** Deprecated `$screen-lg-desktop` as of v3.0.1 +$screen-lg-desktop: $screen-lg-min !default; + +// So media queries don't overlap when required, provide a maximum +$screen-xs-max: ($screen-sm-min - 1) !default; +$screen-sm-max: ($screen-md-min - 1) !default; +$screen-md-max: ($screen-lg-min - 1) !default; + + +//== Grid system +// +//## Define your custom responsive grid. + +//** Number of columns in the grid. +$grid-columns: 12 !default; +//** Padding between columns. Gets divided in half for the left and right. +$grid-gutter-width: 30px !default; +// Navbar collapse +//** Point at which the navbar becomes uncollapsed. +$grid-float-breakpoint: $screen-sm-min !default; +//** Point at which the navbar begins collapsing. +$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default; + + +//== Container sizes +// +//## Define the maximum width of `.container` for different screen sizes. + +// Small screen / tablet +$container-tablet: (720px + $grid-gutter-width) !default; +//** For `$screen-sm-min` and up. +$container-sm: $container-tablet !default; + +// Medium screen / desktop +$container-desktop: (940px + $grid-gutter-width) !default; +//** For `$screen-md-min` and up. +$container-md: $container-desktop !default; + +// Large screen / wide desktop +$container-large-desktop: (1140px + $grid-gutter-width) !default; +//** For `$screen-lg-min` and up. +$container-lg: $container-large-desktop !default; + + +//== Navbar +// +//## + +// Basics of a navbar +$navbar-height: 50px !default; +$navbar-margin-bottom: $line-height-computed !default; +$navbar-border-radius: $border-radius-base !default; +$navbar-padding-horizontal: floor(($grid-gutter-width / 2)) !default; +$navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2) !default; +$navbar-collapse-max-height: 340px !default; + +$navbar-default-color: #777 !default; +$navbar-default-bg: #f8f8f8 !default; +$navbar-default-border: darken($navbar-default-bg, 6.5%) !default; + +// Navbar links +$navbar-default-link-color: #777 !default; +$navbar-default-link-hover-color: #333 !default; +$navbar-default-link-hover-bg: transparent !default; +$navbar-default-link-active-color: #555 !default; +$navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%) !default; +$navbar-default-link-disabled-color: #ccc !default; +$navbar-default-link-disabled-bg: transparent !default; + +// Navbar brand label +$navbar-default-brand-color: $navbar-default-link-color !default; +$navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%) !default; +$navbar-default-brand-hover-bg: transparent !default; + +// Navbar toggle +$navbar-default-toggle-hover-bg: #ddd !default; +$navbar-default-toggle-icon-bar-bg: #888 !default; +$navbar-default-toggle-border-color: #ddd !default; + + +//=== Inverted navbar +// Reset inverted navbar basics +$navbar-inverse-color: lighten($gray-light, 15%) !default; +$navbar-inverse-bg: #222 !default; +$navbar-inverse-border: darken($navbar-inverse-bg, 10%) !default; + +// Inverted navbar links +$navbar-inverse-link-color: lighten($gray-light, 15%) !default; +$navbar-inverse-link-hover-color: #fff !default; +$navbar-inverse-link-hover-bg: transparent !default; +$navbar-inverse-link-active-color: $navbar-inverse-link-hover-color !default; +$navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%) !default; +$navbar-inverse-link-disabled-color: #444 !default; +$navbar-inverse-link-disabled-bg: transparent !default; + +// Inverted navbar brand label +$navbar-inverse-brand-color: $navbar-inverse-link-color !default; +$navbar-inverse-brand-hover-color: #fff !default; +$navbar-inverse-brand-hover-bg: transparent !default; + +// Inverted navbar toggle +$navbar-inverse-toggle-hover-bg: #333 !default; +$navbar-inverse-toggle-icon-bar-bg: #fff !default; +$navbar-inverse-toggle-border-color: #333 !default; + + +//== Navs +// +//## + +//=== Shared nav styles +$nav-link-padding: 10px 15px !default; +$nav-link-hover-bg: $gray-lighter !default; + +$nav-disabled-link-color: $gray-light !default; +$nav-disabled-link-hover-color: $gray-light !default; + +//== Tabs +$nav-tabs-border-color: #ddd !default; + +$nav-tabs-link-hover-border-color: $gray-lighter !default; + +$nav-tabs-active-link-hover-bg: $body-bg !default; +$nav-tabs-active-link-hover-color: $gray !default; +$nav-tabs-active-link-hover-border-color: #ddd !default; + +$nav-tabs-justified-link-border-color: #ddd !default; +$nav-tabs-justified-active-link-border-color: $body-bg !default; + +//== Pills +$nav-pills-border-radius: $border-radius-base !default; +$nav-pills-active-link-hover-bg: $component-active-bg !default; +$nav-pills-active-link-hover-color: $component-active-color !default; + + +//== Pagination +// +//## + +$pagination-color: $link-color !default; +$pagination-bg: #fff !default; +$pagination-border: #ddd !default; + +$pagination-hover-color: $link-hover-color !default; +$pagination-hover-bg: $gray-lighter !default; +$pagination-hover-border: #ddd !default; + +$pagination-active-color: #fff !default; +$pagination-active-bg: $brand-primary !default; +$pagination-active-border: $brand-primary !default; + +$pagination-disabled-color: $gray-light !default; +$pagination-disabled-bg: #fff !default; +$pagination-disabled-border: #ddd !default; + + +//== Pager +// +//## + +$pager-bg: $pagination-bg !default; +$pager-border: $pagination-border !default; +$pager-border-radius: 15px !default; + +$pager-hover-bg: $pagination-hover-bg !default; + +$pager-active-bg: $pagination-active-bg !default; +$pager-active-color: $pagination-active-color !default; + +$pager-disabled-color: $pagination-disabled-color !default; + + +//== Jumbotron +// +//## + +$jumbotron-padding: 30px !default; +$jumbotron-color: inherit !default; +$jumbotron-bg: $gray-lighter !default; +$jumbotron-heading-color: inherit !default; +$jumbotron-font-size: ceil(($font-size-base * 1.5)) !default; +$jumbotron-heading-font-size: ceil(($font-size-base * 4.5)) !default; + + +//== Form states and alerts +// +//## Define colors for form feedback states and, by default, alerts. + +$state-success-text: #3c763d !default; +$state-success-bg: #dff0d8 !default; +$state-success-border: darken(adjust-hue($state-success-bg, -10), 5%) !default; + +$state-info-text: #31708f !default; +$state-info-bg: #d9edf7 !default; +$state-info-border: darken(adjust-hue($state-info-bg, -10), 7%) !default; + +$state-warning-text: #8a6d3b !default; +$state-warning-bg: #fcf8e3 !default; +$state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%) !default; + +$state-danger-text: #a94442 !default; +$state-danger-bg: #f2dede !default; +$state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%) !default; + + +//== Tooltips +// +//## + +//** Tooltip max width +$tooltip-max-width: 200px !default; +//** Tooltip text color +$tooltip-color: #fff !default; +//** Tooltip background color +$tooltip-bg: #000 !default; +$tooltip-opacity: .9 !default; + +//** Tooltip arrow width +$tooltip-arrow-width: 5px !default; +//** Tooltip arrow color +$tooltip-arrow-color: $tooltip-bg !default; + + +//== Popovers +// +//## + +//** Popover body background color +$popover-bg: #fff !default; +//** Popover maximum width +$popover-max-width: 276px !default; +//** Popover border color +$popover-border-color: rgba(0,0,0,.2) !default; +//** Popover fallback border color +$popover-fallback-border-color: #ccc !default; + +//** Popover title background color +$popover-title-bg: darken($popover-bg, 3%) !default; + +//** Popover arrow width +$popover-arrow-width: 10px !default; +//** Popover arrow color +$popover-arrow-color: $popover-bg !default; + +//** Popover outer arrow width +$popover-arrow-outer-width: ($popover-arrow-width + 1) !default; +//** Popover outer arrow color +$popover-arrow-outer-color: fade_in($popover-border-color, 0.05) !default; +//** Popover outer arrow fallback color +$popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%) !default; + + +//== Labels +// +//## + +//** Default label background color +$label-default-bg: $gray-light !default; +//** Primary label background color +$label-primary-bg: $brand-primary !default; +//** Success label background color +$label-success-bg: $brand-success !default; +//** Info label background color +$label-info-bg: $brand-info !default; +//** Warning label background color +$label-warning-bg: $brand-warning !default; +//** Danger label background color +$label-danger-bg: $brand-danger !default; + +//** Default label text color +$label-color: #fff !default; +//** Default text color of a linked label +$label-link-hover-color: #fff !default; + + +//== Modals +// +//## + +//** Padding applied to the modal body +$modal-inner-padding: 15px !default; + +//** Padding applied to the modal title +$modal-title-padding: 15px !default; +//** Modal title line-height +$modal-title-line-height: $line-height-base !default; + +//** Background color of modal content area +$modal-content-bg: #fff !default; +//** Modal content border color +$modal-content-border-color: rgba(0,0,0,.2) !default; +//** Modal content border color **for IE8** +$modal-content-fallback-border-color: #999 !default; + +//** Modal backdrop background color +$modal-backdrop-bg: #000 !default; +//** Modal backdrop opacity +$modal-backdrop-opacity: .5 !default; +//** Modal header border color +$modal-header-border-color: #e5e5e5 !default; +//** Modal footer border color +$modal-footer-border-color: $modal-header-border-color !default; + +$modal-lg: 900px !default; +$modal-md: 600px !default; +$modal-sm: 300px !default; + + +//== Alerts +// +//## Define alert colors, border radius, and padding. + +$alert-padding: 15px !default; +$alert-border-radius: $border-radius-base !default; +$alert-link-font-weight: bold !default; + +$alert-success-bg: $state-success-bg !default; +$alert-success-text: $state-success-text !default; +$alert-success-border: $state-success-border !default; + +$alert-info-bg: $state-info-bg !default; +$alert-info-text: $state-info-text !default; +$alert-info-border: $state-info-border !default; + +$alert-warning-bg: $state-warning-bg !default; +$alert-warning-text: $state-warning-text !default; +$alert-warning-border: $state-warning-border !default; + +$alert-danger-bg: $state-danger-bg !default; +$alert-danger-text: $state-danger-text !default; +$alert-danger-border: $state-danger-border !default; + + +//== Progress bars +// +//## + +//** Background color of the whole progress component +$progress-bg: #f5f5f5 !default; +//** Progress bar text color +$progress-bar-color: #fff !default; +//** Variable for setting rounded corners on progress bar. +$progress-border-radius: $border-radius-base !default; + +//** Default progress bar color +$progress-bar-bg: $brand-primary !default; +//** Success progress bar color +$progress-bar-success-bg: $brand-success !default; +//** Warning progress bar color +$progress-bar-warning-bg: $brand-warning !default; +//** Danger progress bar color +$progress-bar-danger-bg: $brand-danger !default; +//** Info progress bar color +$progress-bar-info-bg: $brand-info !default; + + +//== List group +// +//## + +//** Background color on `.list-group-item` +$list-group-bg: #fff !default; +//** `.list-group-item` border color +$list-group-border: #ddd !default; +//** List group border radius +$list-group-border-radius: $border-radius-base !default; + +//** Background color of single list items on hover +$list-group-hover-bg: #f5f5f5 !default; +//** Text color of active list items +$list-group-active-color: $component-active-color !default; +//** Background color of active list items +$list-group-active-bg: $component-active-bg !default; +//** Border color of active list elements +$list-group-active-border: $list-group-active-bg !default; +//** Text color for content within active list items +$list-group-active-text-color: lighten($list-group-active-bg, 40%) !default; + +//** Text color of disabled list items +$list-group-disabled-color: $gray-light !default; +//** Background color of disabled list items +$list-group-disabled-bg: $gray-lighter !default; +//** Text color for content within disabled list items +$list-group-disabled-text-color: $list-group-disabled-color !default; + +$list-group-link-color: #555 !default; +$list-group-link-hover-color: $list-group-link-color !default; +$list-group-link-heading-color: #333 !default; + + +//== Panels +// +//## + +$panel-bg: #fff !default; +$panel-body-padding: 15px !default; +$panel-heading-padding: 10px 15px !default; +$panel-footer-padding: $panel-heading-padding !default; +$panel-border-radius: $border-radius-base !default; + +//** Border color for elements within panels +$panel-inner-border: #ddd !default; +$panel-footer-bg: #f5f5f5 !default; + +$panel-default-text: $gray-dark !default; +$panel-default-border: #ddd !default; +$panel-default-heading-bg: #f5f5f5 !default; + +$panel-primary-text: #fff !default; +$panel-primary-border: $brand-primary !default; +$panel-primary-heading-bg: $brand-primary !default; + +$panel-success-text: $state-success-text !default; +$panel-success-border: $state-success-border !default; +$panel-success-heading-bg: $state-success-bg !default; + +$panel-info-text: $state-info-text !default; +$panel-info-border: $state-info-border !default; +$panel-info-heading-bg: $state-info-bg !default; + +$panel-warning-text: $state-warning-text !default; +$panel-warning-border: $state-warning-border !default; +$panel-warning-heading-bg: $state-warning-bg !default; + +$panel-danger-text: $state-danger-text !default; +$panel-danger-border: $state-danger-border !default; +$panel-danger-heading-bg: $state-danger-bg !default; + + +//== Thumbnails +// +//## + +//** Padding around the thumbnail image +$thumbnail-padding: 4px !default; +//** Thumbnail background color +$thumbnail-bg: $body-bg !default; +//** Thumbnail border color +$thumbnail-border: #ddd !default; +//** Thumbnail border radius +$thumbnail-border-radius: $border-radius-base !default; + +//** Custom text color for thumbnail captions +$thumbnail-caption-color: $text-color !default; +//** Padding around the thumbnail caption +$thumbnail-caption-padding: 9px !default; + + +//== Wells +// +//## + +$well-bg: #f5f5f5 !default; +$well-border: darken($well-bg, 7%) !default; + + +//== Badges +// +//## + +$badge-color: #fff !default; +//** Linked badge text color on hover +$badge-link-hover-color: #fff !default; +$badge-bg: $gray-light !default; + +//** Badge text color in active nav link +$badge-active-color: $link-color !default; +//** Badge background color in active nav link +$badge-active-bg: #fff !default; + +$badge-font-weight: bold !default; +$badge-line-height: 1 !default; +$badge-border-radius: 10px !default; + + +//== Breadcrumbs +// +//## + +$breadcrumb-padding-vertical: 8px !default; +$breadcrumb-padding-horizontal: 15px !default; +//** Breadcrumb background color +$breadcrumb-bg: #f5f5f5 !default; +//** Breadcrumb text color +$breadcrumb-color: #ccc !default; +//** Text color of current page in the breadcrumb +$breadcrumb-active-color: $gray-light !default; +//** Textual separator for between breadcrumb elements +$breadcrumb-separator: "/" !default; + + +//== Carousel +// +//## + +$carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) !default; + +$carousel-control-color: #fff !default; +$carousel-control-width: 15% !default; +$carousel-control-opacity: .5 !default; +$carousel-control-font-size: 20px !default; + +$carousel-indicator-active-bg: #fff !default; +$carousel-indicator-border-color: #fff !default; + +$carousel-caption-color: #fff !default; + + +//== Close +// +//## + +$close-font-weight: bold !default; +$close-color: #000 !default; +$close-text-shadow: 0 1px 0 #fff !default; + + +//== Code +// +//## + +$code-color: #c7254e !default; +$code-bg: #f9f2f4 !default; + +$kbd-color: #fff !default; +$kbd-bg: #333 !default; + +$pre-bg: #f5f5f5 !default; +$pre-color: $gray-dark !default; +$pre-border-color: #ccc !default; +$pre-scrollable-max-height: 340px !default; + + +//== Type +// +//## + +//** Horizontal offset for forms and lists. +$component-offset-horizontal: 180px !default; +//** Text muted color +$text-muted: $gray-light !default; +//** Abbreviations and acronyms border color +$abbr-border-color: $gray-light !default; +//** Headings small color +$headings-small-color: $gray-light !default; +//** Blockquote small color +$blockquote-small-color: $gray-light !default; +//** Blockquote font size +$blockquote-font-size: ($font-size-base * 1.25) !default; +//** Blockquote border color +$blockquote-border-color: $gray-lighter !default; +//** Page header border color +$page-header-border-color: $gray-lighter !default; +//** Width of horizontal description list titles +$dl-horizontal-offset: $component-offset-horizontal !default; +//** Point at which .dl-horizontal becomes horizontal +$dl-horizontal-breakpoint: $grid-float-breakpoint !default; +//** Horizontal line color. +$hr-border: $gray-lighter !default; diff --git a/www/resources/sass/bootstrap/_wells.scss b/www/resources/sass/bootstrap/_wells.scss new file mode 100644 index 0000000..b865711 --- /dev/null +++ b/www/resources/sass/bootstrap/_wells.scss @@ -0,0 +1,29 @@ +// +// Wells +// -------------------------------------------------- + + +// Base class +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: $well-bg; + border: 1px solid $well-border; + border-radius: $border-radius-base; + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); + blockquote { + border-color: #ddd; + border-color: rgba(0,0,0,.15); + } +} + +// Sizes +.well-lg { + padding: 24px; + border-radius: $border-radius-large; +} +.well-sm { + padding: 9px; + border-radius: $border-radius-small; +} diff --git a/www/resources/sass/bootstrap/mixins/_alerts.scss b/www/resources/sass/bootstrap/mixins/_alerts.scss new file mode 100644 index 0000000..3faf0b5 --- /dev/null +++ b/www/resources/sass/bootstrap/mixins/_alerts.scss @@ -0,0 +1,14 @@ +// Alerts + +@mixin alert-variant($background, $border, $text-color) { + background-color: $background; + border-color: $border; + color: $text-color; + + hr { + border-top-color: darken($border, 5%); + } + .alert-link { + color: darken($text-color, 10%); + } +} diff --git a/www/resources/sass/bootstrap/mixins/_background-variant.scss b/www/resources/sass/bootstrap/mixins/_background-variant.scss new file mode 100644 index 0000000..4c7769e --- /dev/null +++ b/www/resources/sass/bootstrap/mixins/_background-variant.scss @@ -0,0 +1,12 @@ +// Contextual backgrounds + +// [converter] $parent hack +@mixin bg-variant($parent, $color) { + #{$parent} { + background-color: $color; + } + a#{$parent}:hover, + a#{$parent}:focus { + background-color: darken($color, 10%); + } +} diff --git a/www/resources/sass/bootstrap/mixins/_border-radius.scss b/www/resources/sass/bootstrap/mixins/_border-radius.scss new file mode 100644 index 0000000..ce19499 --- /dev/null +++ b/www/resources/sass/bootstrap/mixins/_border-radius.scss @@ -0,0 +1,18 @@ +// Single side border-radius + +@mixin border-top-radius($radius) { + border-top-right-radius: $radius; + border-top-left-radius: $radius; +} +@mixin border-right-radius($radius) { + border-bottom-right-radius: $radius; + border-top-right-radius: $radius; +} +@mixin border-bottom-radius($radius) { + border-bottom-right-radius: $radius; + border-bottom-left-radius: $radius; +} +@mixin border-left-radius($radius) { + border-bottom-left-radius: $radius; + border-top-left-radius: $radius; +} diff --git a/www/resources/sass/bootstrap/mixins/_buttons.scss b/www/resources/sass/bootstrap/mixins/_buttons.scss new file mode 100644 index 0000000..b93f84b --- /dev/null +++ b/www/resources/sass/bootstrap/mixins/_buttons.scss @@ -0,0 +1,65 @@ +// Button variants +// +// Easily pump out default styles, as well as :hover, :focus, :active, +// and disabled options for all buttons + +@mixin button-variant($color, $background, $border) { + color: $color; + background-color: $background; + border-color: $border; + + &:focus, + &.focus { + color: $color; + background-color: darken($background, 10%); + border-color: darken($border, 25%); + } + &:hover { + color: $color; + background-color: darken($background, 10%); + border-color: darken($border, 12%); + } + &:active, + &.active, + .open > &.dropdown-toggle { + color: $color; + background-color: darken($background, 10%); + border-color: darken($border, 12%); + + &:hover, + &:focus, + &.focus { + color: $color; + background-color: darken($background, 17%); + border-color: darken($border, 25%); + } + } + &:active, + &.active, + .open > &.dropdown-toggle { + background-image: none; + } + &.disabled, + &[disabled], + fieldset[disabled] & { + &:hover, + &:focus, + &.focus { + background-color: $background; + border-color: $border; + } + } + + .badge { + color: $background; + background-color: $color; + } +} + +// Button sizes +@mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) { + padding: $padding-vertical $padding-horizontal; + font-size: $font-size; + line-height: $line-height; + border-radius: $border-radius; +} diff --git a/www/resources/sass/bootstrap/mixins/_center-block.scss b/www/resources/sass/bootstrap/mixins/_center-block.scss new file mode 100644 index 0000000..e06fb5e --- /dev/null +++ b/www/resources/sass/bootstrap/mixins/_center-block.scss @@ -0,0 +1,7 @@ +// Center-align a block level element + +@mixin center-block() { + display: block; + margin-left: auto; + margin-right: auto; +} diff --git a/www/resources/sass/bootstrap/mixins/_clearfix.scss b/www/resources/sass/bootstrap/mixins/_clearfix.scss new file mode 100644 index 0000000..dc3e2ab --- /dev/null +++ b/www/resources/sass/bootstrap/mixins/_clearfix.scss @@ -0,0 +1,22 @@ +// Clearfix +// +// For modern browsers +// 1. The space content is one way to avoid an Opera bug when the +// contenteditable attribute is included anywhere else in the document. +// Otherwise it causes space to appear at the top and bottom of elements +// that are clearfixed. +// 2. The use of `table` rather than `block` is only necessary if using +// `:before` to contain the top-margins of child elements. +// +// Source: http://nicolasgallagher.com/micro-clearfix-hack/ + +@mixin clearfix() { + &:before, + &:after { + content: " "; // 1 + display: table; // 2 + } + &:after { + clear: both; + } +} diff --git a/www/resources/sass/bootstrap/mixins/_forms.scss b/www/resources/sass/bootstrap/mixins/_forms.scss new file mode 100644 index 0000000..277aa5f --- /dev/null +++ b/www/resources/sass/bootstrap/mixins/_forms.scss @@ -0,0 +1,88 @@ +// Form validation states +// +// Used in forms.less to generate the form validation CSS for warnings, errors, +// and successes. + +@mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) { + // Color the label and help text + .help-block, + .control-label, + .radio, + .checkbox, + .radio-inline, + .checkbox-inline, + &.radio label, + &.checkbox label, + &.radio-inline label, + &.checkbox-inline label { + color: $text-color; + } + // Set the border and box shadow on specific inputs to match + .form-control { + border-color: $border-color; + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work + &:focus { + border-color: darken($border-color, 10%); + $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%); + @include box-shadow($shadow); + } + } + // Set validation states also for addons + .input-group-addon { + color: $text-color; + border-color: $border-color; + background-color: $background-color; + } + // Optional feedback icon + .form-control-feedback { + color: $text-color; + } +} + + +// Form control focus state +// +// Generate a customized focus state and for any input with the specified color, +// which defaults to the `$input-border-focus` variable. +// +// We highly encourage you to not customize the default value, but instead use +// this to tweak colors on an as-needed basis. This aesthetic change is based on +// WebKit's default styles, but applicable to a wider range of browsers. Its +// usability and accessibility should be taken into account with any change. +// +// Example usage: change the default blue border and shadow to white for better +// contrast against a dark gray background. +@mixin form-control-focus($color: $input-border-focus) { + $color-rgba: rgba(red($color), green($color), blue($color), .6); + &:focus { + border-color: $color; + outline: 0; + @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba); + } +} + +// Form control sizing +// +// Relative text size, padding, and border-radii changes for form controls. For +// horizontal sizing, wrap controls in the predefined grid classes. `