Restructure
24
src-angular/app/app-routing.module.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { RouteReuseStrategy, RouterModule, Routes } from '@angular/router'
|
||||
|
||||
import { BrowseComponent } from './components/browse/browse.component'
|
||||
import { SettingsComponent } from './components/settings/settings.component'
|
||||
import { TabPersistStrategy } from './core/tab-persist.strategy'
|
||||
|
||||
// TODO: replace these with the correct components
|
||||
const routes: Routes = [
|
||||
{ path: 'browse', component: BrowseComponent, data: { shouldReuse: true } },
|
||||
{ path: 'library', redirectTo: '/browse' },
|
||||
{ path: 'settings', component: SettingsComponent, data: { shouldReuse: true } },
|
||||
{ path: 'about', redirectTo: '/browse' },
|
||||
{ path: '**', redirectTo: '/browse' },
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes)],
|
||||
exports: [RouterModule],
|
||||
providers: [
|
||||
{ provide: RouteReuseStrategy, useClass: TabPersistStrategy },
|
||||
],
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
4
src-angular/app/app.component.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<div *ngIf="settingsLoaded" style="display: flex; flex-direction: column; height: 100%">
|
||||
<app-toolbar></app-toolbar>
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
18
src-angular/app/app.component.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
import { SettingsService } from './core/services/settings.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styles: [],
|
||||
})
|
||||
export class AppComponent {
|
||||
|
||||
settingsLoaded = false
|
||||
|
||||
constructor(private settingsService: SettingsService) {
|
||||
// Ensure settings are loaded before rendering the application
|
||||
settingsService.loadSettings().then(() => this.settingsLoaded = true)
|
||||
}
|
||||
}
|
||||
41
src-angular/app/app.module.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module'
|
||||
import { AppComponent } from './app.component'
|
||||
import { BrowseComponent } from './components/browse/browse.component'
|
||||
import { ChartSidebarComponent } from './components/browse/chart-sidebar/chart-sidebar.component'
|
||||
import { ResultTableRowComponent } from './components/browse/result-table/result-table-row/result-table-row.component'
|
||||
import { ResultTableComponent } from './components/browse/result-table/result-table.component'
|
||||
import { SearchBarComponent } from './components/browse/search-bar/search-bar.component'
|
||||
import { DownloadsModalComponent } from './components/browse/status-bar/downloads-modal/downloads-modal.component'
|
||||
import { StatusBarComponent } from './components/browse/status-bar/status-bar.component'
|
||||
import { SettingsComponent } from './components/settings/settings.component'
|
||||
import { ToolbarComponent } from './components/toolbar/toolbar.component'
|
||||
import { CheckboxDirective } from './core/directives/checkbox.directive'
|
||||
import { ProgressBarDirective } from './core/directives/progress-bar.directive'
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
ToolbarComponent,
|
||||
BrowseComponent,
|
||||
SearchBarComponent,
|
||||
StatusBarComponent,
|
||||
ResultTableComponent,
|
||||
ChartSidebarComponent,
|
||||
ResultTableRowComponent,
|
||||
DownloadsModalComponent,
|
||||
ProgressBarDirective,
|
||||
CheckboxDirective,
|
||||
SettingsComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
FormsModule,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule { }
|
||||
12
src-angular/app/components/browse/browse.component.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<app-search-bar></app-search-bar>
|
||||
<div class="ui celled two column grid">
|
||||
<div id="table-row" class="row">
|
||||
<div id="table-column" class="column twelve wide">
|
||||
<app-result-table #resultTable (rowClicked)="chartSidebar.onRowClicked($event)"></app-result-table>
|
||||
</div>
|
||||
<div id="sidebar-column" class="column four wide">
|
||||
<app-chart-sidebar #chartSidebar></app-chart-sidebar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<app-status-bar #statusBar></app-status-bar>
|
||||
27
src-angular/app/components/browse/browse.component.scss
Normal file
@@ -0,0 +1,27 @@
|
||||
:host {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.two.column.grid {
|
||||
display: contents;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#table-row {
|
||||
flex-grow: 1;
|
||||
min-height: 0;
|
||||
flex-wrap: nowrap;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#table-column {
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#sidebar-column {
|
||||
display: flex;
|
||||
min-width: 175px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
35
src-angular/app/components/browse/browse.component.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { AfterViewInit, Component, ViewChild } from '@angular/core'
|
||||
|
||||
import { SearchService } from 'src/app/core/services/search.service'
|
||||
import { ChartSidebarComponent } from './chart-sidebar/chart-sidebar.component'
|
||||
import { ResultTableComponent } from './result-table/result-table.component'
|
||||
import { StatusBarComponent } from './status-bar/status-bar.component'
|
||||
|
||||
@Component({
|
||||
selector: 'app-browse',
|
||||
templateUrl: './browse.component.html',
|
||||
styleUrls: ['./browse.component.scss'],
|
||||
})
|
||||
export class BrowseComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild('resultTable', { static: true }) resultTable: ResultTableComponent
|
||||
@ViewChild('chartSidebar', { static: true }) chartSidebar: ChartSidebarComponent
|
||||
@ViewChild('statusBar', { static: true }) statusBar: StatusBarComponent
|
||||
|
||||
constructor(private searchService: SearchService) { }
|
||||
|
||||
ngAfterViewInit() {
|
||||
const $tableColumn = $('#table-column')
|
||||
$tableColumn.on('scroll', () => {
|
||||
const pos = $tableColumn[0].scrollTop + $tableColumn[0].offsetHeight
|
||||
const max = $tableColumn[0].scrollHeight
|
||||
if (pos >= max - 5) {
|
||||
this.searchService.updateScroll()
|
||||
}
|
||||
})
|
||||
|
||||
this.searchService.onNewSearch(() => {
|
||||
$tableColumn.scrollTop(0)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<div id="sidebarCard" *ngIf="selectedVersion" class="ui fluid card">
|
||||
<div class="ui placeholder" [ngClass]="{ placeholder: albumArtSrc === '', inverted: settingsService.theme === 'Dark' }">
|
||||
<img *ngIf="albumArtSrc !== null" class="ui square image" [src]="albumArtSrc" />
|
||||
</div>
|
||||
<div *ngIf="charts.length > 1" id="chartDropdown" class="ui fluid right labeled scrolling icon dropdown button">
|
||||
<input type="hidden" name="Chart" />
|
||||
<i id="chartDropdownIcon" class="dropdown icon"></i>
|
||||
<div class="default text"></div>
|
||||
<div id="chartDropdownMenu" class="menu"></div>
|
||||
</div>
|
||||
<div id="textPanel" class="content">
|
||||
<span class="header">{{ selectedVersion.chartName }}</span>
|
||||
<div class="description">
|
||||
<div *ngIf="songResult.album === null"><b>Album:</b> {{ selectedVersion.album }} ({{ selectedVersion.year }})</div>
|
||||
<div *ngIf="songResult.album !== null"><b>Year:</b> {{ selectedVersion.year }}</div>
|
||||
<div *ngIf="songResult.genre === null"><b>Genre:</b> {{ selectedVersion.genre }}</div>
|
||||
<div>
|
||||
<b>{{ charterPlural }}</b> {{ selectedVersion.charters }}
|
||||
</div>
|
||||
<div *ngIf="selectedVersion.tags"><b>Tags:</b> {{ selectedVersion.tags }}</div>
|
||||
<div><b>Audio Length:</b> {{ songLength }}</div>
|
||||
<div class="ui divider"></div>
|
||||
<div class="ui horizontal list">
|
||||
<div *ngFor="let difficulty of difficultiesList" class="item">
|
||||
<img class="ui avatar image" src="assets/images/instruments/{{ difficulty.instrument }}" />
|
||||
<div class="content">
|
||||
<div class="header">Diff: {{ difficulty.diffNumber }}</div>
|
||||
{{ difficulty.chartedDifficulties }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sourceLinks">
|
||||
<a id="sourceLink" (click)="onSourceLinkClicked()">{{ selectedVersion.driveData.source.sourceName }}</a>
|
||||
<button *ngIf="shownFolderButton()" id="folderButton" class="mini ui icon button" (click)="onFolderButtonClicked()">
|
||||
<i class="folder open outline icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="downloadButtons" class="ui positive buttons">
|
||||
<div id="downloadButton" class="ui button" (click)="onDownloadClicked()">{{ downloadButtonText }}</div>
|
||||
<div *ngIf="getSelectedChartVersions().length > 1" id="versionDropdown" class="ui floating dropdown icon button">
|
||||
<i class="dropdown icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,64 @@
|
||||
:host {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.ui.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.ui.placeholder {
|
||||
border-radius: 0px !important;
|
||||
}
|
||||
|
||||
#textPanel {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#versionDropdown, #folderButton {
|
||||
max-width: min-content;
|
||||
}
|
||||
|
||||
#chartDropdown {
|
||||
min-height: min-content;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
::ng-deep #chartDropdownMenu > div.item {
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
#sourceLinks {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#sourceLink {
|
||||
align-self: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#chartDropdownIcon, #versionDropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ui.horizontal.list>.item {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.ui.divider {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
#downloadButton {
|
||||
width: min-content;
|
||||
margin: 0px 1px 1px 1px;
|
||||
}
|
||||
|
||||
#versionDropdown {
|
||||
margin: 0px 1px 1px -3px;
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser'
|
||||
|
||||
import { SearchService } from 'src/app/core/services/search.service'
|
||||
import { SettingsService } from 'src/app/core/services/settings.service'
|
||||
import { groupBy } from 'src/electron/shared/UtilFunctions'
|
||||
import { SongResult } from '../../../../electron/shared/interfaces/search.interface'
|
||||
import { ChartedDifficulty, getInstrumentIcon, Instrument, VersionResult } from '../../../../electron/shared/interfaces/songDetails.interface'
|
||||
import { AlbumArtService } from '../../../core/services/album-art.service'
|
||||
import { DownloadService } from '../../../core/services/download.service'
|
||||
import { ElectronService } from '../../../core/services/electron.service'
|
||||
|
||||
interface Difficulty {
|
||||
instrument: string
|
||||
diffNumber: string
|
||||
chartedDifficulties: string
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-chart-sidebar',
|
||||
templateUrl: './chart-sidebar.component.html',
|
||||
styleUrls: ['./chart-sidebar.component.scss'],
|
||||
})
|
||||
export class ChartSidebarComponent implements OnInit {
|
||||
|
||||
songResult: SongResult
|
||||
selectedVersion: VersionResult
|
||||
charts: VersionResult[][]
|
||||
|
||||
albumArtSrc: SafeUrl = ''
|
||||
charterPlural: string
|
||||
songLength: string
|
||||
difficultiesList: Difficulty[]
|
||||
downloadButtonText: string
|
||||
|
||||
constructor(
|
||||
private electronService: ElectronService,
|
||||
private albumArtService: AlbumArtService,
|
||||
private downloadService: DownloadService,
|
||||
private searchService: SearchService,
|
||||
private sanitizer: DomSanitizer,
|
||||
public settingsService: SettingsService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.searchService.onNewSearch(() => {
|
||||
this.selectVersion(undefined)
|
||||
this.songResult = undefined
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the information for the selected song.
|
||||
*/
|
||||
async onRowClicked(result: SongResult) {
|
||||
if (this.songResult == undefined || result.id != this.songResult.id) { // Clicking the same row again will not reload
|
||||
this.songResult = result
|
||||
const albumArt = this.albumArtService.getImage(result.id)
|
||||
const results = await this.electronService.invoke('song-details', result.id)
|
||||
this.charts = groupBy(results, 'chartID').sort((v1, v2) => v1[0].chartName.length - v2[0].chartName.length)
|
||||
this.sortCharts()
|
||||
await this.selectChart(this.charts[0][0].chartID)
|
||||
this.initChartDropdown()
|
||||
|
||||
this.updateAlbumArtSrc(await albumArt)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts `this.charts` and its subarrays in the correct order.
|
||||
* The chart dropdown should display in a random order, but verified charters are prioritized.
|
||||
* The version dropdown should be ordered by lastModified date.
|
||||
* (but prefer the non-pack version if it's only a few days older)
|
||||
*/
|
||||
private sortCharts() {
|
||||
for (const chart of this.charts) {
|
||||
// TODO: sort by verified charter
|
||||
this.searchService.sortChart(chart)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sidebar to display the album art.
|
||||
*/
|
||||
updateAlbumArtSrc(albumArtBase64String?: string) {
|
||||
if (albumArtBase64String) {
|
||||
this.albumArtSrc = this.sanitizer.bypassSecurityTrustUrl('data:image/jpg;base64,' + albumArtBase64String)
|
||||
} else {
|
||||
this.albumArtSrc = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the chart dropdown from `this.charts` (or removes it if there's only one chart).
|
||||
*/
|
||||
private initChartDropdown() {
|
||||
const values = this.charts.map(chart => {
|
||||
const version = chart[0]
|
||||
return {
|
||||
value: version.chartID,
|
||||
text: version.chartName,
|
||||
name: `${version.chartName} <b>[${version.charters}]</b>`,
|
||||
}
|
||||
})
|
||||
const $chartDropdown = $('#chartDropdown')
|
||||
$chartDropdown.dropdown('setup menu', { values })
|
||||
$chartDropdown.dropdown('setting', 'onChange', (chartID: number) => this.selectChart(chartID))
|
||||
$chartDropdown.dropdown('set selected', values[0].value)
|
||||
}
|
||||
|
||||
private async selectChart(chartID: number) {
|
||||
const chart = this.charts.find(chart => chart[0].chartID == chartID)
|
||||
await this.selectVersion(chart[0])
|
||||
this.initVersionDropdown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sidebar to display the metadata for `selectedVersion`.
|
||||
*/
|
||||
async selectVersion(selectedVersion: VersionResult) {
|
||||
this.selectedVersion = selectedVersion
|
||||
await new Promise<void>(resolve => setTimeout(() => resolve(), 0)) // Wait for *ngIf to update DOM
|
||||
|
||||
if (this.selectedVersion != undefined) {
|
||||
this.updateCharterPlural()
|
||||
this.updateSongLength()
|
||||
this.updateDifficultiesList()
|
||||
this.updateDownloadButtonText()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses to display 'Charter:' or 'Charters:'.
|
||||
*/
|
||||
private updateCharterPlural() {
|
||||
this.charterPlural = this.selectedVersion.charterIDs.split('&').length == 1 ? 'Charter:' : 'Charters:'
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts `this.selectedVersion.chartMetadata.length` into a readable duration.
|
||||
*/
|
||||
private updateSongLength() {
|
||||
let seconds = this.selectedVersion.songLength
|
||||
if (seconds < 60) { this.songLength = `${seconds} second${seconds == 1 ? '' : 's'}`; return }
|
||||
let minutes = Math.floor(seconds / 60)
|
||||
let hours = 0
|
||||
while (minutes > 59) {
|
||||
hours++
|
||||
minutes -= 60
|
||||
}
|
||||
seconds = Math.floor(seconds % 60)
|
||||
this.songLength = `${hours == 0 ? '' : hours + ':'}${minutes == 0 ? '' : minutes + ':'}${seconds < 10 ? '0' + seconds : seconds}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates `dfficultiesList` with the difficulty information for the selected version.
|
||||
*/
|
||||
private updateDifficultiesList() {
|
||||
const instruments = Object.keys(this.selectedVersion.chartData.noteCounts) as Instrument[]
|
||||
this.difficultiesList = []
|
||||
for (const instrument of instruments) {
|
||||
if (instrument != 'undefined') {
|
||||
this.difficultiesList.push({
|
||||
instrument: getInstrumentIcon(instrument),
|
||||
diffNumber: this.getDiffNumber(instrument),
|
||||
chartedDifficulties: this.getChartedDifficultiesText(instrument),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a string describing the difficulty number in the selected version.
|
||||
*/
|
||||
private getDiffNumber(instrument: Instrument) {
|
||||
const diffNumber: number = (this.selectedVersion as any)[`diff_${instrument}`]
|
||||
return diffNumber == -1 || diffNumber == undefined ? 'Unknown' : String(diffNumber)
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a string describing the list of charted difficulties in the selected version.
|
||||
*/
|
||||
private getChartedDifficultiesText(instrument: Instrument) {
|
||||
const difficulties = Object.keys(this.selectedVersion.chartData.noteCounts[instrument]) as ChartedDifficulty[]
|
||||
if (difficulties.length == 4) { return 'Full Difficulty' }
|
||||
const difficultyNames = []
|
||||
if (difficulties.includes('x')) { difficultyNames.push('Expert') }
|
||||
if (difficulties.includes('h')) { difficultyNames.push('Hard') }
|
||||
if (difficulties.includes('m')) { difficultyNames.push('Medium') }
|
||||
if (difficulties.includes('e')) { difficultyNames.push('Easy') }
|
||||
|
||||
return difficultyNames.join(', ')
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses the text to display on the download button.
|
||||
*/
|
||||
private updateDownloadButtonText() {
|
||||
this.downloadButtonText = 'Download'
|
||||
if (this.selectedVersion.driveData.inChartPack) {
|
||||
this.downloadButtonText += ' Chart Pack'
|
||||
} else {
|
||||
this.downloadButtonText += (this.selectedVersion.driveData.isArchive ? ' Archive' : ' Files')
|
||||
}
|
||||
|
||||
if (this.getSelectedChartVersions().length > 1) {
|
||||
if (this.selectedVersion.versionID == this.selectedVersion.latestVersionID) {
|
||||
this.downloadButtonText += ' (Latest)'
|
||||
} else {
|
||||
this.downloadButtonText += ` (${this.getLastModifiedText(this.selectedVersion.lastModified)})`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the version dropdown from `this.selectedVersion` (or removes it if there's only one version).
|
||||
*/
|
||||
private initVersionDropdown() {
|
||||
const $versionDropdown = $('#versionDropdown')
|
||||
const versions = this.getSelectedChartVersions()
|
||||
const values = versions.map(version => ({
|
||||
value: version.versionID,
|
||||
text: 'Uploaded ' + this.getLastModifiedText(version.lastModified),
|
||||
name: 'Uploaded ' + this.getLastModifiedText(version.lastModified),
|
||||
}))
|
||||
|
||||
$versionDropdown.dropdown('setup menu', { values })
|
||||
$versionDropdown.dropdown('setting', 'onChange', (versionID: number) => {
|
||||
this.selectVersion(versions.find(version => version.versionID == versionID))
|
||||
})
|
||||
$versionDropdown.dropdown('set selected', values[0].value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of versions for the selected chart, sorted by `lastModified`.
|
||||
*/
|
||||
getSelectedChartVersions() {
|
||||
return this.charts.find(chart => chart[0].chartID == this.selectedVersion.chartID)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the <lastModified> value to a user-readable format.
|
||||
* @param lastModified The UNIX timestamp for the lastModified date.
|
||||
*/
|
||||
private getLastModifiedText(lastModified: string) {
|
||||
const date = new Date(lastModified)
|
||||
const day = date.getDate().toString().padStart(2, '0')
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
||||
const year = date.getFullYear().toString().substr(-2)
|
||||
return `${month}/${day}/${year}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the proxy link or source folder in the default browser.
|
||||
*/
|
||||
onSourceLinkClicked() {
|
||||
const source = this.selectedVersion.driveData.source
|
||||
this.electronService.sendIPC('open-url', source.proxyLink ?? `https://drive.google.com/drive/folders/${source.sourceDriveID}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns `true` if the source folder button should be shown.
|
||||
*/
|
||||
shownFolderButton() {
|
||||
const driveData = this.selectedVersion.driveData
|
||||
return driveData.source.proxyLink || driveData.source.sourceDriveID != driveData.folderID
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the chart folder in the default browser.
|
||||
*/
|
||||
onFolderButtonClicked() {
|
||||
this.electronService.sendIPC('open-url', `https://drive.google.com/drive/folders/${this.selectedVersion.driveData.folderID}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the selected version to the download queue.
|
||||
*/
|
||||
onDownloadClicked() {
|
||||
this.downloadService.addDownload(
|
||||
this.selectedVersion.versionID, {
|
||||
chartName: this.selectedVersion.chartName,
|
||||
artist: this.songResult.artist,
|
||||
charter: this.selectedVersion.charters,
|
||||
driveData: this.selectedVersion.driveData,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<td>
|
||||
<div #checkbox class="ui checkbox" (click)="$event.stopPropagation()">
|
||||
<input type="checkbox" />
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span id="chartCount" *ngIf="result.chartCount > 1">{{ result.chartCount }}</span
|
||||
>{{ result.name }}
|
||||
</td>
|
||||
<td>{{ result.artist }}</td>
|
||||
<td>{{ result.album || 'Various' }}</td>
|
||||
<td>{{ result.genre || 'Various' }}</td>
|
||||
@@ -0,0 +1,10 @@
|
||||
.ui.checkbox {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#chartCount {
|
||||
background-color: lightgray;
|
||||
border-radius: 3px;
|
||||
padding: 1px 4px 2px 4px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core'
|
||||
|
||||
import { SongResult } from '../../../../../electron/shared/interfaces/search.interface'
|
||||
import { SelectionService } from '../../../../core/services/selection.service'
|
||||
|
||||
@Component({
|
||||
selector: 'tr[app-result-table-row]',
|
||||
templateUrl: './result-table-row.component.html',
|
||||
styleUrls: ['./result-table-row.component.scss'],
|
||||
})
|
||||
export class ResultTableRowComponent implements AfterViewInit {
|
||||
@Input() result: SongResult
|
||||
|
||||
@ViewChild('checkbox', { static: true }) checkbox: ElementRef
|
||||
|
||||
constructor(private selectionService: SelectionService) { }
|
||||
|
||||
get songID() {
|
||||
return this.result.id
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.selectionService.onSelectionChanged(this.songID, isChecked => {
|
||||
if (isChecked) {
|
||||
$(this.checkbox.nativeElement).checkbox('check')
|
||||
} else {
|
||||
$(this.checkbox.nativeElement).checkbox('uncheck')
|
||||
}
|
||||
})
|
||||
|
||||
$(this.checkbox.nativeElement).checkbox({
|
||||
onChecked: () => {
|
||||
this.selectionService.selectSong(this.songID)
|
||||
},
|
||||
onUnchecked: () => {
|
||||
this.selectionService.deselectSong(this.songID)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<table
|
||||
id="resultTable"
|
||||
class="ui stackable selectable single sortable fixed line striped compact small table"
|
||||
[class.inverted]="settingsService.theme === 'Dark'">
|
||||
<!-- TODO: maybe have some of these tags customizable? E.g. small/large/compact/padded -->
|
||||
<!-- TODO: learn semantic themes in order to change the $mobileBreakpoint global variable (better search table adjustment) -->
|
||||
<thead>
|
||||
<!-- NOTE: it would be nice to make this header sticky, but Fomantic-UI doesn't currently support that -->
|
||||
<tr>
|
||||
<th class="collapsing" id="checkboxColumn">
|
||||
<div class="ui checkbox" id="checkbox" #checkboxColumn appCheckbox (checked)="checkAll($event)">
|
||||
<input type="checkbox" />
|
||||
</div>
|
||||
</th>
|
||||
<th class="four wide" [class.sorted]="sortColumn === 'name'" [ngClass]="sortDirection" (click)="onColClicked('name')">Name</th>
|
||||
<th class="four wide" [class.sorted]="sortColumn === 'artist'" [ngClass]="sortDirection" (click)="onColClicked('artist')">Artist</th>
|
||||
<th class="four wide" [class.sorted]="sortColumn === 'album'" [ngClass]="sortDirection" (click)="onColClicked('album')">Album</th>
|
||||
<th class="four wide" [class.sorted]="sortColumn === 'genre'" [ngClass]="sortDirection" (click)="onColClicked('genre')">Genre</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
app-result-table-row
|
||||
#tableRow
|
||||
*ngFor="let result of results"
|
||||
(click)="onRowClicked(result)"
|
||||
[class.active]="activeRowID === result.id"
|
||||
[result]="result"></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -0,0 +1,25 @@
|
||||
:host {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.ui.checkbox {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#checkboxColumn {
|
||||
width: 34.64px;
|
||||
}
|
||||
|
||||
#resultTable {
|
||||
border-radius: 0px;
|
||||
|
||||
thead>tr:first-child>th:first-child,
|
||||
thead>tr:first-child>th:last-child {
|
||||
border-radius: 0px;
|
||||
}
|
||||
th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index:1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import { Component, EventEmitter, OnInit, Output, QueryList, ViewChild, ViewChildren } from '@angular/core'
|
||||
|
||||
import Comparators from 'comparators'
|
||||
|
||||
import { SettingsService } from 'src/app/core/services/settings.service'
|
||||
import { SongResult } from '../../../../electron/shared/interfaces/search.interface'
|
||||
import { CheckboxDirective } from '../../../core/directives/checkbox.directive'
|
||||
import { SearchService } from '../../../core/services/search.service'
|
||||
import { SelectionService } from '../../../core/services/selection.service'
|
||||
import { ResultTableRowComponent } from './result-table-row/result-table-row.component'
|
||||
|
||||
@Component({
|
||||
selector: 'app-result-table',
|
||||
templateUrl: './result-table.component.html',
|
||||
styleUrls: ['./result-table.component.scss'],
|
||||
})
|
||||
export class ResultTableComponent implements OnInit {
|
||||
|
||||
@Output() rowClicked = new EventEmitter<SongResult>()
|
||||
|
||||
@ViewChild(CheckboxDirective, { static: true }) checkboxColumn: CheckboxDirective
|
||||
@ViewChildren('tableRow') tableRows: QueryList<ResultTableRowComponent>
|
||||
|
||||
results: SongResult[] = []
|
||||
activeRowID: number = null
|
||||
sortDirection: 'ascending' | 'descending' = 'descending'
|
||||
sortColumn: 'name' | 'artist' | 'album' | 'genre' | null = null
|
||||
|
||||
constructor(
|
||||
private searchService: SearchService,
|
||||
private selectionService: SelectionService,
|
||||
public settingsService: SettingsService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.selectionService.onSelectAllChanged(selected => {
|
||||
this.checkboxColumn.check(selected)
|
||||
})
|
||||
|
||||
this.searchService.onSearchChanged(results => {
|
||||
this.activeRowID = null
|
||||
this.results = results
|
||||
this.updateSort()
|
||||
})
|
||||
|
||||
this.searchService.onNewSearch(() => {
|
||||
this.sortColumn = null
|
||||
})
|
||||
}
|
||||
|
||||
onRowClicked(result: SongResult) {
|
||||
this.activeRowID = result.id
|
||||
this.rowClicked.emit(result)
|
||||
}
|
||||
|
||||
onColClicked(column: 'name' | 'artist' | 'album' | 'genre') {
|
||||
if (this.results.length == 0) { return }
|
||||
if (this.sortColumn != column) {
|
||||
this.sortColumn = column
|
||||
this.sortDirection = 'descending'
|
||||
} else if (this.sortDirection == 'descending') {
|
||||
this.sortDirection = 'ascending'
|
||||
} else {
|
||||
this.sortDirection = 'descending'
|
||||
}
|
||||
this.updateSort()
|
||||
}
|
||||
|
||||
private updateSort() {
|
||||
if (this.sortColumn != null) {
|
||||
this.results.sort(Comparators.comparing(this.sortColumn, { reversed: this.sortDirection == 'ascending' }))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user checks the `checkboxColumn`.
|
||||
*/
|
||||
checkAll(isChecked: boolean) {
|
||||
if (isChecked) {
|
||||
this.selectionService.selectAll()
|
||||
} else {
|
||||
this.selectionService.deselectAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
<div id="searchMenu" class="ui bottom attached borderless menu">
|
||||
<div class="item">
|
||||
<div class="ui icon input" [class.loading]="isLoading()">
|
||||
<input #searchBox type="text" placeholder=" Search..." (keyup.enter)="onSearch(searchBox.value)" />
|
||||
<i
|
||||
#searchIcon
|
||||
id="searchIcon"
|
||||
class="link icon"
|
||||
[ngClass]="isError ? 'red exclamation triangle' : 'search'"
|
||||
data-content="Failed to connect to the Bridge database"
|
||||
data-position="bottom right"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="quantityDropdownItem" [class.hidden]="!showAdvanced" class="item">
|
||||
<div #quantityDropdown class="ui compact selection dropdown">
|
||||
<input name="quantityMatch" type="hidden" />
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="text"><b>all</b> words match</div>
|
||||
<div class="menu">
|
||||
<div id="dropdownItem" class="active selected item" data-value="all"><b>all</b> words match</div>
|
||||
<div id="dropdownItem" class="item" data-value="any"><b>any</b> words match</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="similarityDropdownItem" [class.hidden]="!showAdvanced" class="item">
|
||||
<div #similarityDropdown class="ui compact selection dropdown">
|
||||
<input name="similarityMatch" type="hidden" value="similar" />
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="text"><b>similar</b> words match</div>
|
||||
<div class="menu">
|
||||
<div id="dropdownItem" class="active selected item" data-value="similar"><b>similar</b> words match</div>
|
||||
<div id="dropdownItem" class="item" data-value="exact"><b>exact</b> words match</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item right">
|
||||
<button class="mini ui right labeled icon button" (click)="onAdvancedSearchClick()">
|
||||
Advanced Search
|
||||
<i class="angle double icon" [ngClass]="showAdvanced ? 'up' : 'down'"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="advancedSearchForm" [class.collapsed]="!showAdvanced" class="ui horizontal segments">
|
||||
<div class="ui secondary segment">
|
||||
<div class="grouped fields">
|
||||
<h5 class="ui dividing header">Search for</h5>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="name" [(ngModel)]="searchSettings.fields.name" />
|
||||
<label>Name</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="artist" [(ngModel)]="searchSettings.fields.artist" />
|
||||
<label>Artist</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="album" [(ngModel)]="searchSettings.fields.album" />
|
||||
<label>Album</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="genre" [(ngModel)]="searchSettings.fields.genre" />
|
||||
<label>Genre</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="year" [(ngModel)]="searchSettings.fields.year" />
|
||||
<label>Year</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="charter" [(ngModel)]="searchSettings.fields.charter" />
|
||||
<label>Charter</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="tag" [(ngModel)]="searchSettings.fields.tag" />
|
||||
<label>Tag</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui secondary segment">
|
||||
<div class="grouped fields">
|
||||
<h5 class="ui dividing header">Must include</h5>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="sections" [(ngModel)]="searchSettings.tags.sections" />
|
||||
<label>Sections</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="starpower" [(ngModel)]="searchSettings.tags['star power']" />
|
||||
<label>Star Power</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="forcing" [(ngModel)]="searchSettings.tags.forcing" />
|
||||
<label>Forcing</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="taps" [(ngModel)]="searchSettings.tags.taps" />
|
||||
<label>Taps</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="lyrics" [(ngModel)]="searchSettings.tags.lyrics" />
|
||||
<label>Lyrics</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="videobackground" [(ngModel)]="searchSettings.tags.video" />
|
||||
<label>Video Background</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="stems" [(ngModel)]="searchSettings.tags.stems" />
|
||||
<label>Audio Stems</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="solosections" [(ngModel)]="searchSettings.tags['solo sections']" />
|
||||
<label>Solo Sections</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="opennotes" [(ngModel)]="searchSettings.tags['open notes']" />
|
||||
<label>Open Notes</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui secondary segment">
|
||||
<div class="grouped fields">
|
||||
<h5 class="ui dividing header">Instruments</h5>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="guitar" [(ngModel)]="searchSettings.instruments.guitar" />
|
||||
<label>Guitar</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="bass" [(ngModel)]="searchSettings.instruments.bass" />
|
||||
<label>Bass</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="rhythm" [(ngModel)]="searchSettings.instruments.rhythm" />
|
||||
<label>Rhythm</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="keys" [(ngModel)]="searchSettings.instruments.keys" />
|
||||
<label>Keys</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="drums" [(ngModel)]="searchSettings.instruments.drums" />
|
||||
<label>Drums</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="guitarghl" [(ngModel)]="searchSettings.instruments.guitarghl" />
|
||||
<label>GHL Guitar</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="bassghl" [(ngModel)]="searchSettings.instruments.bassghl" />
|
||||
<label>GHL Bass</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="vocals" [(ngModel)]="searchSettings.instruments.vocals" />
|
||||
<label>Vocals</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui secondary segment">
|
||||
<h5 class="ui dividing header">Charted difficulties</h5>
|
||||
<div class="grouped fields">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="expert" [(ngModel)]="searchSettings.difficulties.expert" />
|
||||
<label>Expert</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="hard" [(ngModel)]="searchSettings.difficulties.hard" />
|
||||
<label>Hard</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="medium" [(ngModel)]="searchSettings.difficulties.medium" />
|
||||
<label>Medium</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="easy" [(ngModel)]="searchSettings.difficulties.easy" />
|
||||
<label>Easy</label>
|
||||
</div>
|
||||
</div>
|
||||
<h5 class="ui dividing header">Difficulty range</h5>
|
||||
<div class="field">
|
||||
<div #diffSlider class="ui labeled ticked inverted range slider" id="diffSlider"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,51 @@
|
||||
#searchMenu {
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 0em;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
#searchMenu>.item {
|
||||
padding: .3em .4em;
|
||||
min-height: inherit;
|
||||
}
|
||||
|
||||
#searchMenu>.item:first-child {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
#searchIcon {
|
||||
cursor: default;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#advancedSearchForm {
|
||||
margin: 0em;
|
||||
border-width: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height 350ms cubic-bezier(0.45, 0, 0.55, 1);
|
||||
max-height: 243.913px; /* This is its preferred height. Transition needs a static target number to work. */
|
||||
}
|
||||
|
||||
.collapsed {
|
||||
max-height: 0px !important;
|
||||
}
|
||||
|
||||
#quantityDropdownItem, #similarityDropdownItem {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
max-width: 100vw;
|
||||
max-height: 100vh;
|
||||
transition: visibility 0s, opacity 350ms cubic-bezier(0.45, 0, 0.55, 1);
|
||||
}
|
||||
|
||||
.hidden {
|
||||
opacity: 0 !important;
|
||||
visibility: hidden !important;
|
||||
max-width: 0px !important;
|
||||
max-height: 0px !important;
|
||||
transition:
|
||||
opacity 350ms cubic-bezier(0.45, 0, 0.55, 1),
|
||||
visibility 0s linear 350ms,
|
||||
max-width 0s linear 350ms,
|
||||
max-height 0s linear 350ms !important;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core'
|
||||
|
||||
import { SearchService } from 'src/app/core/services/search.service'
|
||||
import { getDefaultSearch } from 'src/electron/shared/interfaces/search.interface'
|
||||
|
||||
@Component({
|
||||
selector: 'app-search-bar',
|
||||
templateUrl: './search-bar.component.html',
|
||||
styleUrls: ['./search-bar.component.scss'],
|
||||
})
|
||||
export class SearchBarComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild('searchIcon', { static: true }) searchIcon: ElementRef
|
||||
@ViewChild('quantityDropdown', { static: true }) quantityDropdown: ElementRef
|
||||
@ViewChild('similarityDropdown', { static: true }) similarityDropdown: ElementRef
|
||||
@ViewChild('diffSlider', { static: true }) diffSlider: ElementRef
|
||||
|
||||
isError = false
|
||||
showAdvanced = false
|
||||
searchSettings = getDefaultSearch()
|
||||
private sliderInitialized = false
|
||||
|
||||
constructor(public searchService: SearchService) { }
|
||||
|
||||
ngAfterViewInit() {
|
||||
$(this.searchIcon.nativeElement).popup({
|
||||
onShow: () => this.isError, // Only show the popup if there is an error
|
||||
})
|
||||
this.searchService.onSearchErrorStateUpdate(isError => {
|
||||
this.isError = isError
|
||||
})
|
||||
$(this.quantityDropdown.nativeElement).dropdown({
|
||||
onChange: (value: string) => {
|
||||
this.searchSettings.quantity = value as 'all' | 'any'
|
||||
},
|
||||
})
|
||||
$(this.similarityDropdown.nativeElement).dropdown({
|
||||
onChange: (value: string) => {
|
||||
this.searchSettings.similarity = value as 'similar' | 'exact'
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
onSearch(query: string) {
|
||||
this.searchSettings.query = query
|
||||
this.searchSettings.limit = 50 + 1
|
||||
this.searchSettings.offset = 0
|
||||
this.searchService.newSearch(this.searchSettings)
|
||||
}
|
||||
|
||||
onAdvancedSearchClick() {
|
||||
this.showAdvanced = !this.showAdvanced
|
||||
|
||||
if (!this.sliderInitialized) {
|
||||
setTimeout(() => { // Initialization requires this element to not be collapsed
|
||||
$(this.diffSlider.nativeElement).slider({
|
||||
min: 0,
|
||||
max: 6,
|
||||
start: 0,
|
||||
end: 6,
|
||||
step: 1,
|
||||
onChange: (_length: number, min: number, max: number) => {
|
||||
this.searchSettings.minDiff = min
|
||||
this.searchSettings.maxDiff = max
|
||||
},
|
||||
})
|
||||
}, 50)
|
||||
this.sliderInitialized = true
|
||||
}
|
||||
}
|
||||
|
||||
isLoading() {
|
||||
return this.searchService.isLoading()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<div *ngIf="downloads.length > 0" class="ui segments">
|
||||
<div *ngFor="let download of downloads; trackBy: trackByVersionID" class="ui segment" [style.background-color]="getBackgroundColor(download)">
|
||||
<h3 id="downloadTitle">
|
||||
<span style="flex-grow: 1">{{ download.title }}</span>
|
||||
<i class="inside right close icon" (click)="cancelDownload(download.versionID)"></i>
|
||||
</h3>
|
||||
|
||||
<div id="downloadText">
|
||||
<span style="flex-grow: 1">{{ download.header }}</span>
|
||||
<span *ngIf="!download.isLink" class="description">{{ download.description }}</span>
|
||||
<span *ngIf="download.isLink" class="description">
|
||||
<a (click)="openFolder(download.description)">{{ download.description }}</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="downloadProgressDiv">
|
||||
<div id="downloadProgressBar" appProgressBar [percent]="download.percent" class="ui small progress">
|
||||
<div class="bar" [style.height]="download.type === 'error' ? '-webkit-fill-available' : undefined">
|
||||
<div class="progress"></div>
|
||||
</div>
|
||||
</div>
|
||||
<button *ngIf="download.type === 'error'" class="ui right attached labeled compact icon button" (click)="retryDownload(download.versionID)">
|
||||
<i class="redo icon"></i>
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,26 @@
|
||||
#downloadTitle,
|
||||
#downloadText {
|
||||
display: flex;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
#downloadText {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#downloadProgressDiv {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#downloadProgressBar {
|
||||
flex-grow: 1;
|
||||
margin: 0;
|
||||
.bar {
|
||||
transform: translateY(-50%);
|
||||
top: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
i.close.icon, a {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { ChangeDetectorRef, Component } from '@angular/core'
|
||||
|
||||
import { DownloadProgress } from '../../../../../electron/shared/interfaces/download.interface'
|
||||
import { DownloadService } from '../../../../core/services/download.service'
|
||||
import { ElectronService } from '../../../../core/services/electron.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-downloads-modal',
|
||||
templateUrl: './downloads-modal.component.html',
|
||||
styleUrls: ['./downloads-modal.component.scss'],
|
||||
})
|
||||
export class DownloadsModalComponent {
|
||||
|
||||
downloads: DownloadProgress[] = []
|
||||
|
||||
constructor(private electronService: ElectronService, private downloadService: DownloadService, ref: ChangeDetectorRef) {
|
||||
electronService.receiveIPC('queue-updated', order => {
|
||||
this.downloads.sort((a, b) => order.indexOf(a.versionID) - order.indexOf(b.versionID))
|
||||
})
|
||||
|
||||
downloadService.onDownloadUpdated(download => {
|
||||
const index = this.downloads.findIndex(thisDownload => thisDownload.versionID == download.versionID)
|
||||
if (download.type == 'cancel') {
|
||||
this.downloads = this.downloads.filter(thisDownload => thisDownload.versionID != download.versionID)
|
||||
} else if (index == -1) {
|
||||
this.downloads.push(download)
|
||||
} else {
|
||||
this.downloads[index] = download
|
||||
}
|
||||
ref.detectChanges()
|
||||
})
|
||||
}
|
||||
|
||||
trackByVersionID(_index: number, item: DownloadProgress) {
|
||||
return item.versionID
|
||||
}
|
||||
|
||||
cancelDownload(versionID: number) {
|
||||
this.downloadService.cancelDownload(versionID)
|
||||
}
|
||||
|
||||
retryDownload(versionID: number) {
|
||||
this.downloadService.retryDownload(versionID)
|
||||
}
|
||||
|
||||
getBackgroundColor(download: DownloadProgress) {
|
||||
switch (download.type) {
|
||||
case 'error': return '#a63a3a'
|
||||
default: return undefined
|
||||
}
|
||||
}
|
||||
|
||||
openFolder(filepath: string) {
|
||||
this.electronService.showFolder(filepath)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<div id="bottomMenu" class="ui bottom borderless menu">
|
||||
<div *ngIf="resultCount > 0" class="item">{{ resultCount }}{{ allResultsVisible ? '' : '+' }} Result{{ resultCount === 1 ? '' : 's' }}</div>
|
||||
<div class="item">
|
||||
<button *ngIf="selectedResults.length > 1" (click)="downloadSelected()" class="ui positive button">
|
||||
Download {{ selectedResults.length }} Results
|
||||
</button>
|
||||
</div>
|
||||
<a *ngIf="downloading" class="item right" (click)="showDownloads()">
|
||||
<div #progressBar appProgressBar [percent]="percent" class="ui progress" [style.background-color]="error ? 'indianred' : undefined">
|
||||
<div class="bar">
|
||||
<div class="progress"></div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div id="selectedModal" class="ui modal">
|
||||
<div class="header">Some selected songs have more than one chart!</div>
|
||||
<div class="scrolling content">
|
||||
<div class="ui segments">
|
||||
<div class="ui segment" *ngFor="let chartGroup of chartGroups">
|
||||
<p *ngFor="let chart of chartGroup">
|
||||
{{ chart.chartName }} <b>[{{ chart.charters }}]</b>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="ui approve button" (click)="downloadAllCharts()">Download all charts for each song</div>
|
||||
<div class="ui cancel button" (click)="deselectSongsWithMultipleCharts()">Deselect these songs</div>
|
||||
<div class="ui cancel button">Cancel</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="downloadsModal" class="ui modal">
|
||||
<i class="inside close icon"></i>
|
||||
<div class="header">
|
||||
<span>Downloads</span>
|
||||
<div *ngIf="multipleCompleted" class="ui positive compact button" (click)="clearCompleted()">Clear completed</div>
|
||||
</div>
|
||||
<div class="scrolling content">
|
||||
<app-downloads-modal></app-downloads-modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
.ui.progress {
|
||||
margin: 0;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
#bottomMenu {
|
||||
border-radius: 0px;
|
||||
border-width: 1px 0px 0px 0px;
|
||||
}
|
||||
|
||||
#downloadsModal {
|
||||
.header {
|
||||
display: flex;
|
||||
|
||||
span {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.ui.positive.button {
|
||||
margin-right: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import { ChangeDetectorRef, Component } from '@angular/core'
|
||||
|
||||
import { VersionResult } from '../../../../electron/shared/interfaces/songDetails.interface'
|
||||
import { groupBy } from '../../../../electron/shared/UtilFunctions'
|
||||
import { DownloadService } from '../../../core/services/download.service'
|
||||
import { ElectronService } from '../../../core/services/electron.service'
|
||||
import { SearchService } from '../../../core/services/search.service'
|
||||
import { SelectionService } from '../../../core/services/selection.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-status-bar',
|
||||
templateUrl: './status-bar.component.html',
|
||||
styleUrls: ['./status-bar.component.scss'],
|
||||
})
|
||||
export class StatusBarComponent {
|
||||
|
||||
resultCount = 0
|
||||
multipleCompleted = false
|
||||
downloading = false
|
||||
error = false
|
||||
percent = 0
|
||||
batchResults: VersionResult[]
|
||||
chartGroups: VersionResult[][]
|
||||
|
||||
constructor(
|
||||
private electronService: ElectronService,
|
||||
private downloadService: DownloadService,
|
||||
private searchService: SearchService,
|
||||
private selectionService: SelectionService,
|
||||
ref: ChangeDetectorRef
|
||||
) {
|
||||
downloadService.onDownloadUpdated(() => {
|
||||
setTimeout(() => { // Make sure this is the last callback executed to get the accurate downloadCount
|
||||
this.downloading = downloadService.downloadCount > 0
|
||||
this.multipleCompleted = downloadService.completedCount > 1
|
||||
this.percent = downloadService.totalDownloadingPercent
|
||||
this.error = downloadService.anyErrorsExist
|
||||
ref.detectChanges()
|
||||
}, 0)
|
||||
})
|
||||
|
||||
searchService.onSearchChanged(() => {
|
||||
this.resultCount = searchService.resultCount
|
||||
})
|
||||
}
|
||||
|
||||
get allResultsVisible() {
|
||||
return this.searchService.allResultsVisible
|
||||
}
|
||||
|
||||
get selectedResults() {
|
||||
return this.selectionService.getSelectedResults()
|
||||
}
|
||||
|
||||
showDownloads() {
|
||||
$('#downloadsModal').modal('show')
|
||||
}
|
||||
|
||||
async downloadSelected() {
|
||||
this.chartGroups = []
|
||||
this.batchResults = await this.electronService.invoke('batch-song-details', this.selectedResults.map(result => result.id))
|
||||
const versionGroups = groupBy(this.batchResults, 'songID')
|
||||
for (const versionGroup of versionGroups) {
|
||||
if (versionGroup.findIndex(version => version.chartID != versionGroup[0].chartID) != -1) {
|
||||
// Must have multiple charts of this song
|
||||
this.chartGroups.push(versionGroup.filter(version => version.versionID == version.latestVersionID))
|
||||
}
|
||||
}
|
||||
|
||||
if (this.chartGroups.length == 0) {
|
||||
for (const versions of versionGroups) {
|
||||
this.searchService.sortChart(versions)
|
||||
const downloadVersion = versions[0]
|
||||
const downloadSong = this.selectedResults.find(song => song.id == downloadVersion.songID)
|
||||
this.downloadService.addDownload(
|
||||
downloadVersion.versionID, {
|
||||
chartName: downloadVersion.chartName,
|
||||
artist: downloadSong.artist,
|
||||
charter: downloadVersion.charters,
|
||||
driveData: downloadVersion.driveData,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
$('#selectedModal').modal('show')
|
||||
// [download all charts for each song] [deselect these songs] [X]
|
||||
}
|
||||
}
|
||||
|
||||
downloadAllCharts() {
|
||||
const songChartGroups = groupBy(this.batchResults, 'songID', 'chartID')
|
||||
for (const chart of songChartGroups) {
|
||||
this.searchService.sortChart(chart)
|
||||
const downloadVersion = chart[0]
|
||||
const downloadSong = this.selectedResults.find(song => song.id == downloadVersion.songID)
|
||||
this.downloadService.addDownload(
|
||||
downloadVersion.versionID, {
|
||||
chartName: downloadVersion.chartName,
|
||||
artist: downloadSong.artist,
|
||||
charter: downloadVersion.charters,
|
||||
driveData: downloadVersion.driveData,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
deselectSongsWithMultipleCharts() {
|
||||
for (const chartGroup of this.chartGroups) {
|
||||
this.selectionService.deselectSong(chartGroup[0].songID)
|
||||
}
|
||||
}
|
||||
|
||||
clearCompleted() {
|
||||
this.downloadService.cancelCompleted()
|
||||
}
|
||||
}
|
||||
71
src-angular/app/components/settings/settings.component.html
Normal file
@@ -0,0 +1,71 @@
|
||||
<h3 class="ui header">Paths</h3>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label>Chart library directory</label>
|
||||
<div class="ui action input">
|
||||
<input
|
||||
[value]="settingsService.libraryDirectory || 'No folder selected'"
|
||||
class="default-cursor"
|
||||
readonly
|
||||
type="text"
|
||||
placeholder="No directory selected!" />
|
||||
<button *ngIf="settingsService.libraryDirectory !== undefined" (click)="openLibraryDirectory()" class="ui button">Open Folder</button>
|
||||
<button (click)="getLibraryDirectory()" class="ui button positive">Choose</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="ui header">Cache</h3>
|
||||
<div>
|
||||
Current Cache Size:
|
||||
<div class="ui label" style="margin-left: 1em">{{ cacheSize }}</div>
|
||||
</div>
|
||||
<button style="margin-top: 0.5em" (click)="clearCache()" class="ui button">Clear Cache</button>
|
||||
|
||||
<h3 class="ui header">Downloads</h3>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<div appCheckbox #videoCheckbox class="ui checkbox" (checked)="downloadVideos($event)">
|
||||
<input type="checkbox" />
|
||||
<label>Download video backgrounds</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Google rate limit delay</label>
|
||||
<div id="rateLimitInput" class="ui right labeled input">
|
||||
<input type="number" [value]="settingsService.rateLimitDelay" (input)="changeRateLimit($event)" />
|
||||
<div class="ui basic label">sec</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="settingsService.rateLimitDelay < 30" class="ui warning message">
|
||||
<i class="exclamation circle icon"></i>
|
||||
<b>Warning:</b> downloading files from Google with a delay less than about 30 seconds will eventually cause Google to refuse download requests from
|
||||
this program for a few hours. This limitation will be removed in a future update.
|
||||
</div>
|
||||
|
||||
<h3 class="ui header">Theme</h3>
|
||||
<div #themeDropdown class="ui selection dropdown mr">
|
||||
<input type="hidden" name="sort" [value]="settingsService.theme" />
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="default text">{{ settingsService.theme }}</div>
|
||||
<div class="menu">
|
||||
<div class="item" [attr.data-value]="i" *ngFor="let theme of settingsService.builtinThemes; let i = index">{{ theme }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bottom">
|
||||
<div class="ui buttons">
|
||||
<button *ngIf="updateAvailable" class="ui labeled icon positive button" (click)="downloadUpdate()">
|
||||
<i class="left alternate icon" [ngClass]="updateDownloaded ? 'sync' : 'cloud download'"></i>{{ downloadUpdateText }}
|
||||
</button>
|
||||
<button *ngIf="updateAvailable === null" class="ui labeled yellow icon button" [class.disabled]="updateRetrying" (click)="retryUpdate()">
|
||||
<i class="left alternate sync alternate icon" [class.loading]="updateRetrying"></i>{{ retryUpdateText }}
|
||||
</button>
|
||||
<button id="versionNumberButton" class="ui basic disabled button">{{ currentVersion }}</button>
|
||||
</div>
|
||||
|
||||
<button class="ui basic icon button" data-tooltip="Toggle developer tools" data-position="top right" (click)="toggleDevTools()">
|
||||
<i class="cog icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
24
src-angular/app/components/settings/settings.component.scss
Normal file
@@ -0,0 +1,24 @@
|
||||
:host {
|
||||
flex: 1;
|
||||
padding: 2em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.default-cursor {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#rateLimitInput {
|
||||
width: unset !important;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
position: absolute;
|
||||
bottom: 2em;
|
||||
right: 2em;
|
||||
}
|
||||
|
||||
#versionNumberButton {
|
||||
margin-right: 1em;
|
||||
}
|
||||
140
src-angular/app/components/settings/settings.component.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'
|
||||
|
||||
import { CheckboxDirective } from 'src/app/core/directives/checkbox.directive'
|
||||
import { ElectronService } from 'src/app/core/services/electron.service'
|
||||
import { SettingsService } from 'src/app/core/services/settings.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
templateUrl: './settings.component.html',
|
||||
styleUrls: ['./settings.component.scss'],
|
||||
})
|
||||
export class SettingsComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('themeDropdown', { static: true }) themeDropdown: ElementRef
|
||||
@ViewChild(CheckboxDirective, { static: true }) videoCheckbox: CheckboxDirective
|
||||
|
||||
cacheSize = 'Calculating...'
|
||||
updateAvailable = false
|
||||
loginClicked = false
|
||||
downloadUpdateText = 'Update available'
|
||||
retryUpdateText = 'Failed to check for update'
|
||||
updateDownloading = false
|
||||
updateDownloaded = false
|
||||
updateRetrying = false
|
||||
currentVersion = ''
|
||||
|
||||
constructor(
|
||||
public settingsService: SettingsService,
|
||||
private electronService: ElectronService,
|
||||
private ref: ChangeDetectorRef
|
||||
) { }
|
||||
|
||||
async ngOnInit() {
|
||||
this.electronService.receiveIPC('update-available', result => {
|
||||
this.updateAvailable = result != null
|
||||
this.updateRetrying = false
|
||||
if (this.updateAvailable) {
|
||||
this.downloadUpdateText = `Update available (${result.version})`
|
||||
}
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
this.electronService.receiveIPC('update-error', (err: Error) => {
|
||||
console.log(err)
|
||||
this.updateAvailable = null
|
||||
this.updateRetrying = false
|
||||
this.retryUpdateText = `Failed to check for update: ${err.message}`
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
this.electronService.invoke('get-current-version', undefined).then(version => {
|
||||
this.currentVersion = `v${version}`
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
this.electronService.invoke('get-update-available', undefined).then(isAvailable => {
|
||||
this.updateAvailable = isAvailable
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
|
||||
const cacheSize = await this.settingsService.getCacheSize()
|
||||
this.cacheSize = Math.round(cacheSize / 1000000) + ' MB'
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
$(this.themeDropdown.nativeElement).dropdown({
|
||||
onChange: (_value: string, text: string) => {
|
||||
this.settingsService.theme = text
|
||||
},
|
||||
})
|
||||
|
||||
this.videoCheckbox.check(this.settingsService.downloadVideos)
|
||||
}
|
||||
|
||||
async clearCache() {
|
||||
this.cacheSize = 'Please wait...'
|
||||
await this.settingsService.clearCache()
|
||||
this.cacheSize = 'Cleared!'
|
||||
}
|
||||
|
||||
async downloadVideos(isChecked: boolean) {
|
||||
this.settingsService.downloadVideos = isChecked
|
||||
}
|
||||
|
||||
async getLibraryDirectory() {
|
||||
const result = await this.electronService.showOpenDialog({
|
||||
title: 'Choose library folder',
|
||||
buttonLabel: 'This is where my charts are!',
|
||||
defaultPath: this.settingsService.libraryDirectory || '',
|
||||
properties: ['openDirectory'],
|
||||
})
|
||||
|
||||
if (result.canceled == false) {
|
||||
this.settingsService.libraryDirectory = result.filePaths[0]
|
||||
}
|
||||
}
|
||||
|
||||
openLibraryDirectory() {
|
||||
this.electronService.openFolder(this.settingsService.libraryDirectory)
|
||||
}
|
||||
|
||||
changeRateLimit(event: Event) {
|
||||
const inputElement = event.srcElement as HTMLInputElement
|
||||
this.settingsService.rateLimitDelay = Number(inputElement.value)
|
||||
}
|
||||
|
||||
downloadUpdate() {
|
||||
if (this.updateDownloaded) {
|
||||
this.electronService.sendIPC('quit-and-install', undefined)
|
||||
} else if (!this.updateDownloading) {
|
||||
this.updateDownloading = true
|
||||
this.electronService.sendIPC('download-update', undefined)
|
||||
this.downloadUpdateText = 'Downloading... (0%)'
|
||||
this.electronService.receiveIPC('update-progress', result => {
|
||||
this.downloadUpdateText = `Downloading... (${result.percent.toFixed(0)}%)`
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
this.electronService.receiveIPC('update-downloaded', () => {
|
||||
this.downloadUpdateText = 'Quit and install update'
|
||||
this.updateDownloaded = true
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
retryUpdate() {
|
||||
if (this.updateRetrying == false) {
|
||||
this.updateRetrying = true
|
||||
this.retryUpdateText = 'Retrying...'
|
||||
this.ref.detectChanges()
|
||||
this.electronService.sendIPC('retry-update', undefined)
|
||||
}
|
||||
}
|
||||
|
||||
toggleDevTools() {
|
||||
const toolsOpened = this.electronService.currentWindow.webContents.isDevToolsOpened()
|
||||
|
||||
if (toolsOpened) {
|
||||
this.electronService.currentWindow.webContents.closeDevTools()
|
||||
} else {
|
||||
this.electronService.currentWindow.webContents.openDevTools()
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src-angular/app/components/toolbar/toolbar.component.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<div class="ui top menu">
|
||||
<a class="item" routerLinkActive="active" routerLink="/browse">Browse</a>
|
||||
<!-- TODO <a class="item" routerLinkActive="active" routerLink="/library">Library</a> -->
|
||||
<a class="item" routerLinkActive="active" routerLink="/settings">
|
||||
<i *ngIf="updateAvailable" class="teal small circle icon"></i>
|
||||
<i *ngIf="updateAvailable === null" class="small yellow exclamation triangle icon"></i>
|
||||
Settings
|
||||
</a>
|
||||
|
||||
<div class="right menu">
|
||||
<a class="item traffic-light" (click)="minimize()"><i class="minus icon"></i></a>
|
||||
<a class="item traffic-light" (click)="toggleMaximized()"><i class="icon window" [ngClass]="isMaximized ? 'restore' : 'maximize'"></i></a>
|
||||
<a class="item traffic-light close" (click)="close()"><i class="x icon"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
27
src-angular/app/components/toolbar/toolbar.component.scss
Normal file
@@ -0,0 +1,27 @@
|
||||
.menu {
|
||||
-webkit-app-region: drag;
|
||||
z-index: 9000 !important;
|
||||
border: 0px;
|
||||
border-radius: 0px;
|
||||
|
||||
.item,
|
||||
.item * {
|
||||
border-radius: 0px;
|
||||
-webkit-app-region: no-drag;
|
||||
cursor: default !important;
|
||||
}
|
||||
}
|
||||
|
||||
.traffic-light {
|
||||
&:before {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
i {
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
background: rgba(255, 0, 0, .15) !important;
|
||||
}
|
||||
56
src-angular/app/components/toolbar/toolbar.component.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core'
|
||||
|
||||
import { ElectronService } from '../../core/services/electron.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-toolbar',
|
||||
templateUrl: './toolbar.component.html',
|
||||
styleUrls: ['./toolbar.component.scss'],
|
||||
})
|
||||
export class ToolbarComponent implements OnInit {
|
||||
|
||||
isMaximized: boolean
|
||||
updateAvailable = false
|
||||
|
||||
constructor(private electronService: ElectronService, private ref: ChangeDetectorRef) { }
|
||||
|
||||
async ngOnInit() {
|
||||
this.isMaximized = this.electronService.currentWindow.isMaximized()
|
||||
this.electronService.currentWindow.on('unmaximize', () => {
|
||||
this.isMaximized = false
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
this.electronService.currentWindow.on('maximize', () => {
|
||||
this.isMaximized = true
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
|
||||
this.electronService.receiveIPC('update-available', result => {
|
||||
this.updateAvailable = result != null
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
this.electronService.receiveIPC('update-error', () => {
|
||||
this.updateAvailable = null
|
||||
this.ref.detectChanges()
|
||||
})
|
||||
this.updateAvailable = await this.electronService.invoke('get-update-available', undefined)
|
||||
this.ref.detectChanges()
|
||||
}
|
||||
|
||||
minimize() {
|
||||
this.electronService.currentWindow.minimize()
|
||||
}
|
||||
|
||||
toggleMaximized() {
|
||||
if (this.isMaximized) {
|
||||
this.electronService.currentWindow.restore()
|
||||
} else {
|
||||
this.electronService.currentWindow.maximize()
|
||||
}
|
||||
this.isMaximized = !this.isMaximized
|
||||
}
|
||||
|
||||
close() {
|
||||
this.electronService.quit()
|
||||
}
|
||||
}
|
||||
38
src-angular/app/core/directives/checkbox.directive.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { AfterViewInit, Directive, ElementRef, EventEmitter, Output } from '@angular/core'
|
||||
|
||||
@Directive({
|
||||
selector: '[appCheckbox]',
|
||||
})
|
||||
export class CheckboxDirective implements AfterViewInit {
|
||||
@Output() checked = new EventEmitter<boolean>()
|
||||
|
||||
_isChecked = false
|
||||
|
||||
constructor(private checkbox: ElementRef) { }
|
||||
|
||||
ngAfterViewInit() {
|
||||
$(this.checkbox.nativeElement).checkbox({
|
||||
onChecked: () => {
|
||||
this.checked.emit(true)
|
||||
this._isChecked = true
|
||||
},
|
||||
onUnchecked: () => {
|
||||
this.checked.emit(false)
|
||||
this._isChecked = false
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
check(isChecked: boolean) {
|
||||
this._isChecked = isChecked
|
||||
if (isChecked) {
|
||||
$(this.checkbox.nativeElement).checkbox('check')
|
||||
} else {
|
||||
$(this.checkbox.nativeElement).checkbox('uncheck')
|
||||
}
|
||||
}
|
||||
|
||||
get isChecked() {
|
||||
return this._isChecked
|
||||
}
|
||||
}
|
||||
29
src-angular/app/core/directives/progress-bar.directive.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Directive, ElementRef, Input } from '@angular/core'
|
||||
|
||||
import * as _ from 'lodash'
|
||||
|
||||
@Directive({
|
||||
selector: '[appProgressBar]',
|
||||
})
|
||||
export class ProgressBarDirective {
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private _$progressBar: any
|
||||
|
||||
progress: (percent: number) => void
|
||||
|
||||
@Input() set percent(percent: number) {
|
||||
this.progress(percent)
|
||||
}
|
||||
|
||||
constructor(private element: ElementRef) {
|
||||
this.progress = _.throttle((percent: number) => this.$progressBar.progress('set').percent(percent), 100)
|
||||
}
|
||||
|
||||
private get $progressBar() {
|
||||
if (!this._$progressBar) {
|
||||
this._$progressBar = $(this.element.nativeElement)
|
||||
}
|
||||
return this._$progressBar
|
||||
}
|
||||
}
|
||||
26
src-angular/app/core/services/album-art.service.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
|
||||
import { ElectronService } from './electron.service'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AlbumArtService {
|
||||
|
||||
private imageCache: { [songID: number]: string } = {}
|
||||
|
||||
constructor(private electronService: ElectronService) { }
|
||||
|
||||
async getImage(songID: number): Promise<string | null> {
|
||||
if (this.imageCache[songID] == undefined) {
|
||||
const albumArtResult = await this.electronService.invoke('album-art', songID)
|
||||
if (albumArtResult) {
|
||||
this.imageCache[songID] = albumArtResult.base64Art
|
||||
} else {
|
||||
this.imageCache[songID] = null
|
||||
}
|
||||
}
|
||||
|
||||
return this.imageCache[songID]
|
||||
}
|
||||
}
|
||||
89
src-angular/app/core/services/download.service.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { EventEmitter, Injectable } from '@angular/core'
|
||||
|
||||
import { DownloadProgress, NewDownload } from '../../../electron/shared/interfaces/download.interface'
|
||||
import { ElectronService } from './electron.service'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DownloadService {
|
||||
|
||||
private downloadUpdatedEmitter = new EventEmitter<DownloadProgress>()
|
||||
private downloads: DownloadProgress[] = []
|
||||
|
||||
constructor(private electronService: ElectronService) {
|
||||
this.electronService.receiveIPC('download-updated', result => {
|
||||
// Update <this.downloads> with result
|
||||
const thisDownloadIndex = this.downloads.findIndex(download => download.versionID == result.versionID)
|
||||
if (result.type == 'cancel') {
|
||||
this.downloads = this.downloads.filter(download => download.versionID != result.versionID)
|
||||
} else if (thisDownloadIndex == -1) {
|
||||
this.downloads.push(result)
|
||||
} else {
|
||||
this.downloads[thisDownloadIndex] = result
|
||||
}
|
||||
|
||||
this.downloadUpdatedEmitter.emit(result)
|
||||
})
|
||||
}
|
||||
|
||||
get downloadCount() {
|
||||
return this.downloads.length
|
||||
}
|
||||
|
||||
get completedCount() {
|
||||
return this.downloads.filter(download => download.type == 'done').length
|
||||
}
|
||||
|
||||
get totalDownloadingPercent() {
|
||||
let total = 0
|
||||
let count = 0
|
||||
for (const download of this.downloads) {
|
||||
if (!download.stale) {
|
||||
total += download.percent
|
||||
count++
|
||||
}
|
||||
}
|
||||
return total / count
|
||||
}
|
||||
|
||||
get anyErrorsExist() {
|
||||
return this.downloads.find(download => download.type == 'error') ? true : false
|
||||
}
|
||||
|
||||
addDownload(versionID: number, newDownload: NewDownload) {
|
||||
if (!this.downloads.find(download => download.versionID == versionID)) { // Don't download something twice
|
||||
if (this.downloads.every(download => download.type == 'done')) { // Reset overall progress bar if it finished
|
||||
this.downloads.forEach(download => download.stale = true)
|
||||
}
|
||||
this.electronService.sendIPC('download', { action: 'add', versionID, data: newDownload })
|
||||
}
|
||||
}
|
||||
|
||||
onDownloadUpdated(callback: (download: DownloadProgress) => void) {
|
||||
this.downloadUpdatedEmitter.subscribe(callback)
|
||||
}
|
||||
|
||||
cancelDownload(versionID: number) {
|
||||
const removedDownload = this.downloads.find(download => download.versionID == versionID)
|
||||
if (['error', 'done'].includes(removedDownload.type)) {
|
||||
this.downloads = this.downloads.filter(download => download.versionID != versionID)
|
||||
removedDownload.type = 'cancel'
|
||||
this.downloadUpdatedEmitter.emit(removedDownload)
|
||||
} else {
|
||||
this.electronService.sendIPC('download', { action: 'cancel', versionID })
|
||||
}
|
||||
}
|
||||
|
||||
cancelCompleted() {
|
||||
for (const download of this.downloads) {
|
||||
if (download.type == 'done') {
|
||||
this.cancelDownload(download.versionID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retryDownload(versionID: number) {
|
||||
this.electronService.sendIPC('download', { action: 'retry', versionID })
|
||||
}
|
||||
}
|
||||
81
src-angular/app/core/services/electron.service.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
|
||||
// If you import a module but never use any of the imported values other than as TypeScript types,
|
||||
// the resulting javascript file will look as if you never imported the module at all.
|
||||
import * as electron from 'electron'
|
||||
|
||||
import { IPCEmitEvents, IPCInvokeEvents } from '../../../electron/shared/IPCHandler'
|
||||
|
||||
const { app, getCurrentWindow, dialog, session } = window.require('@electron/remote')
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ElectronService {
|
||||
electron: typeof electron
|
||||
|
||||
get isElectron() {
|
||||
return !!(window && window.process && window.process.type)
|
||||
}
|
||||
|
||||
constructor() {
|
||||
if (this.isElectron) {
|
||||
this.electron = window.require('electron')
|
||||
this.receiveIPC('log', results => results.forEach(result => console.log(result)))
|
||||
}
|
||||
}
|
||||
|
||||
get currentWindow() {
|
||||
return getCurrentWindow()
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls an async function in the main process.
|
||||
* @param event The name of the IPC event to invoke.
|
||||
* @param data The data object to send across IPC.
|
||||
* @returns A promise that resolves to the output data.
|
||||
*/
|
||||
async invoke<E extends keyof IPCInvokeEvents>(event: E, data: IPCInvokeEvents[E]['input']) {
|
||||
return this.electron.ipcRenderer.invoke(event, data) as Promise<IPCInvokeEvents[E]['output']>
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an IPC message to the main process.
|
||||
* @param event The name of the IPC event to send.
|
||||
* @param data The data object to send across IPC.
|
||||
*/
|
||||
sendIPC<E extends keyof IPCEmitEvents>(event: E, data: IPCEmitEvents[E]) {
|
||||
this.electron.ipcRenderer.send(event, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives an IPC message from the main process.
|
||||
* @param event The name of the IPC event to receive.
|
||||
* @param callback The data object to receive across IPC.
|
||||
*/
|
||||
receiveIPC<E extends keyof IPCEmitEvents>(event: E, callback: (result: IPCEmitEvents[E]) => void) {
|
||||
this.electron.ipcRenderer.on(event, (_event, ...results) => {
|
||||
callback(results[0])
|
||||
})
|
||||
}
|
||||
|
||||
quit() {
|
||||
app.exit()
|
||||
}
|
||||
|
||||
openFolder(filepath: string) {
|
||||
this.electron.shell.openPath(filepath)
|
||||
}
|
||||
|
||||
showFolder(filepath: string) {
|
||||
this.electron.shell.showItemInFolder(filepath)
|
||||
}
|
||||
|
||||
showOpenDialog(options: Electron.OpenDialogOptions) {
|
||||
return dialog.showOpenDialog(this.currentWindow, options)
|
||||
}
|
||||
|
||||
get defaultSession() {
|
||||
return session.defaultSession
|
||||
}
|
||||
}
|
||||
119
src-angular/app/core/services/search.service.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { EventEmitter, Injectable } from '@angular/core'
|
||||
|
||||
import { SongResult, SongSearch } from 'src/electron/shared/interfaces/search.interface'
|
||||
import { VersionResult } from 'src/electron/shared/interfaces/songDetails.interface'
|
||||
import { ElectronService } from './electron.service'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class SearchService {
|
||||
|
||||
private resultsChangedEmitter = new EventEmitter<SongResult[]>() // For when any results change
|
||||
private newResultsEmitter = new EventEmitter<SongResult[]>() // For when a new search happens
|
||||
private errorStateEmitter = new EventEmitter<boolean>() // To indicate the search's error state
|
||||
private results: SongResult[] = []
|
||||
private awaitingResults = false
|
||||
private currentQuery: SongSearch
|
||||
private _allResultsVisible = true
|
||||
|
||||
constructor(private electronService: ElectronService) { }
|
||||
|
||||
async newSearch(query: SongSearch) {
|
||||
if (this.awaitingResults) { return }
|
||||
this.awaitingResults = true
|
||||
this.currentQuery = query
|
||||
try {
|
||||
this.results = this.trimLastChart(await this.electronService.invoke('song-search', this.currentQuery))
|
||||
this.errorStateEmitter.emit(false)
|
||||
} catch (err) {
|
||||
this.results = []
|
||||
console.log(err.message)
|
||||
this.errorStateEmitter.emit(true)
|
||||
}
|
||||
this.awaitingResults = false
|
||||
|
||||
this.newResultsEmitter.emit(this.results)
|
||||
this.resultsChangedEmitter.emit(this.results)
|
||||
}
|
||||
|
||||
isLoading() {
|
||||
return this.awaitingResults
|
||||
}
|
||||
|
||||
/**
|
||||
* Event emitted when new search results are returned
|
||||
* or when more results are added to an existing search.
|
||||
* (emitted after `onNewSearch`)
|
||||
*/
|
||||
onSearchChanged(callback: (results: SongResult[]) => void) {
|
||||
this.resultsChangedEmitter.subscribe(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Event emitted when a new search query is typed in.
|
||||
* (emitted before `onSearchChanged`)
|
||||
*/
|
||||
onNewSearch(callback: (results: SongResult[]) => void) {
|
||||
this.newResultsEmitter.subscribe(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Event emitted when the error state of the search changes.
|
||||
* (emitted before `onSearchChanged`)
|
||||
*/
|
||||
onSearchErrorStateUpdate(callback: (isError: boolean) => void) {
|
||||
this.errorStateEmitter.subscribe(callback)
|
||||
}
|
||||
|
||||
get resultCount() {
|
||||
return this.results.length
|
||||
}
|
||||
|
||||
async updateScroll() {
|
||||
if (!this.awaitingResults && !this._allResultsVisible) {
|
||||
this.awaitingResults = true
|
||||
this.currentQuery.offset += 50
|
||||
this.results.push(...this.trimLastChart(await this.electronService.invoke('song-search', this.currentQuery)))
|
||||
this.awaitingResults = false
|
||||
|
||||
this.resultsChangedEmitter.emit(this.results)
|
||||
}
|
||||
}
|
||||
|
||||
trimLastChart(results: SongResult[]) {
|
||||
if (results.length > 50) {
|
||||
results.splice(50, 1)
|
||||
this._allResultsVisible = false
|
||||
} else {
|
||||
this._allResultsVisible = true
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
get allResultsVisible() {
|
||||
return this._allResultsVisible
|
||||
}
|
||||
|
||||
/**
|
||||
* Orders `versionResults` by lastModified date, but prefer the
|
||||
* non-pack version if it's only a few days older.
|
||||
*/
|
||||
sortChart(versionResults: VersionResult[]) {
|
||||
const dates: { [versionID: number]: number } = {}
|
||||
versionResults.forEach(version => dates[version.versionID] = new Date(version.lastModified).getTime())
|
||||
versionResults.sort((v1, v2) => {
|
||||
const diff = dates[v2.versionID] - dates[v1.versionID]
|
||||
if (Math.abs(diff) < 6.048e+8 && v1.driveData.inChartPack != v2.driveData.inChartPack) {
|
||||
if (v1.driveData.inChartPack) {
|
||||
return 1 // prioritize v2
|
||||
} else {
|
||||
return -1 // prioritize v1
|
||||
}
|
||||
} else {
|
||||
return diff
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
85
src-angular/app/core/services/selection.service.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { EventEmitter, Injectable } from '@angular/core'
|
||||
|
||||
import { SongResult } from '../../../electron/shared/interfaces/search.interface'
|
||||
import { SearchService } from './search.service'
|
||||
|
||||
// Note: this class prevents event cycles by only emitting events if the checkbox changes
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class SelectionService {
|
||||
|
||||
private searchResults: SongResult[] = []
|
||||
|
||||
private selectAllChangedEmitter = new EventEmitter<boolean>()
|
||||
private selectionChangedCallbacks: { [songID: number]: (selection: boolean) => void } = {}
|
||||
|
||||
private allSelected = false
|
||||
private selections: { [songID: number]: boolean | undefined } = {}
|
||||
|
||||
constructor(searchService: SearchService) {
|
||||
searchService.onSearchChanged(results => {
|
||||
this.searchResults = results
|
||||
if (this.allSelected) {
|
||||
this.selectAll() // Select newly added rows if allSelected
|
||||
}
|
||||
})
|
||||
|
||||
searchService.onNewSearch(results => {
|
||||
this.searchResults = results
|
||||
this.selectionChangedCallbacks = {}
|
||||
this.selections = {}
|
||||
this.selectAllChangedEmitter.emit(false)
|
||||
})
|
||||
}
|
||||
|
||||
getSelectedResults() {
|
||||
return this.searchResults.filter(result => this.selections[result.id] == true)
|
||||
}
|
||||
|
||||
onSelectAllChanged(callback: (selected: boolean) => void) {
|
||||
this.selectAllChangedEmitter.subscribe(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an event when the selection for `songID` needs to change.
|
||||
* (note: only one emitter can be registered per `songID`)
|
||||
*/
|
||||
onSelectionChanged(songID: number, callback: (selection: boolean) => void) {
|
||||
this.selectionChangedCallbacks[songID] = callback
|
||||
}
|
||||
|
||||
|
||||
deselectAll() {
|
||||
if (this.allSelected) {
|
||||
this.allSelected = false
|
||||
this.selectAllChangedEmitter.emit(false)
|
||||
}
|
||||
|
||||
setTimeout(() => this.searchResults.forEach(result => this.deselectSong(result.id)), 0)
|
||||
}
|
||||
|
||||
selectAll() {
|
||||
if (!this.allSelected) {
|
||||
this.allSelected = true
|
||||
this.selectAllChangedEmitter.emit(true)
|
||||
}
|
||||
|
||||
setTimeout(() => this.searchResults.forEach(result => this.selectSong(result.id)), 0)
|
||||
}
|
||||
|
||||
deselectSong(songID: number) {
|
||||
if (this.selections[songID]) {
|
||||
this.selections[songID] = false
|
||||
this.selectionChangedCallbacks[songID](false)
|
||||
}
|
||||
}
|
||||
|
||||
selectSong(songID: number) {
|
||||
if (!this.selections[songID]) {
|
||||
this.selections[songID] = true
|
||||
this.selectionChangedCallbacks[songID](true)
|
||||
}
|
||||
}
|
||||
}
|
||||
82
src-angular/app/core/services/settings.service.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
|
||||
import { Settings } from 'src/electron/shared/Settings'
|
||||
import { ElectronService } from './electron.service'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class SettingsService {
|
||||
readonly builtinThemes = ['Default', 'Dark']
|
||||
|
||||
private settings: Settings
|
||||
private currentThemeLink: HTMLLinkElement
|
||||
|
||||
constructor(private electronService: ElectronService) { }
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = await this.electronService.invoke('get-settings', undefined)
|
||||
if (this.settings.theme != this.builtinThemes[0]) {
|
||||
this.changeTheme(this.settings.theme)
|
||||
}
|
||||
}
|
||||
|
||||
saveSettings() {
|
||||
this.electronService.sendIPC('set-settings', this.settings)
|
||||
}
|
||||
|
||||
changeTheme(theme: string) {
|
||||
if (this.currentThemeLink != undefined) this.currentThemeLink.remove()
|
||||
if (theme == 'Default') { return }
|
||||
|
||||
const link = document.createElement('link')
|
||||
link.type = 'text/css'
|
||||
link.rel = 'stylesheet'
|
||||
link.href = `./assets/themes/${theme.toLowerCase()}.css`
|
||||
this.currentThemeLink = document.head.appendChild(link)
|
||||
}
|
||||
|
||||
async getCacheSize() {
|
||||
return this.electronService.defaultSession.getCacheSize()
|
||||
}
|
||||
|
||||
async clearCache() {
|
||||
this.saveSettings()
|
||||
await this.electronService.defaultSession.clearCache()
|
||||
await this.electronService.invoke('clear-cache', undefined)
|
||||
}
|
||||
|
||||
// Individual getters/setters
|
||||
get libraryDirectory() {
|
||||
return this.settings.libraryPath
|
||||
}
|
||||
set libraryDirectory(newValue: string) {
|
||||
this.settings.libraryPath = newValue
|
||||
this.saveSettings()
|
||||
}
|
||||
|
||||
get downloadVideos() {
|
||||
return this.settings.downloadVideos
|
||||
}
|
||||
set downloadVideos(isChecked) {
|
||||
this.settings.downloadVideos = isChecked
|
||||
this.saveSettings()
|
||||
}
|
||||
|
||||
get theme() {
|
||||
return this.settings.theme
|
||||
}
|
||||
set theme(newValue: string) {
|
||||
this.settings.theme = newValue
|
||||
this.changeTheme(newValue)
|
||||
this.saveSettings()
|
||||
}
|
||||
|
||||
get rateLimitDelay() {
|
||||
return this.settings.rateLimitDelay
|
||||
}
|
||||
set rateLimitDelay(delay: number) {
|
||||
this.settings.rateLimitDelay = delay
|
||||
this.saveSettings()
|
||||
}
|
||||
}
|
||||
29
src-angular/app/core/tab-persist.strategy.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router'
|
||||
|
||||
/**
|
||||
* This makes each route with the 'reuse' data flag persist when not in focus.
|
||||
*/
|
||||
@Injectable()
|
||||
export class TabPersistStrategy extends RouteReuseStrategy {
|
||||
private handles: { [path: string]: DetachedRouteHandle } = {}
|
||||
|
||||
shouldDetach(route: ActivatedRouteSnapshot) {
|
||||
return route.data.shouldReuse || false
|
||||
}
|
||||
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle) {
|
||||
if (route.data.shouldReuse) {
|
||||
this.handles[route.routeConfig.path] = handle
|
||||
}
|
||||
}
|
||||
shouldAttach(route: ActivatedRouteSnapshot) {
|
||||
return !!route.routeConfig && !!this.handles[route.routeConfig.path]
|
||||
}
|
||||
retrieve(route: ActivatedRouteSnapshot) {
|
||||
if (!route.routeConfig) return null
|
||||
return this.handles[route.routeConfig.path]
|
||||
}
|
||||
shouldReuseRoute(future: ActivatedRouteSnapshot) {
|
||||
return future.data.shouldReuse || false
|
||||
}
|
||||
}
|
||||
0
src-angular/assets/.gitkeep
Normal file
BIN
src-angular/assets/images/bridge-animation.gif
Normal file
|
After Width: | Height: | Size: 266 KiB |
BIN
src-angular/assets/images/example.png
Normal file
|
After Width: | Height: | Size: 381 KiB |
BIN
src-angular/assets/images/instruments/bass.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
src-angular/assets/images/instruments/bassghl.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
src-angular/assets/images/instruments/drums.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
src-angular/assets/images/instruments/guitar.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
src-angular/assets/images/instruments/guitarghl.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
src-angular/assets/images/instruments/keys.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src-angular/assets/images/instruments/rhythm.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
src-angular/assets/images/instruments/vocals.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
src-angular/assets/images/logo-sm.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
16
src-angular/assets/images/logo.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 835 445" style="enable-background:new 0 0 835 445;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;}
|
||||
</style>
|
||||
<path class="st0" d="M5,5L5,5v180c0,41.4,33.6,75,75,75l0,0l0,0c41.4,0,75-33.6,75-75l0,0c0-41.4-33.6-75-75-75l0,0
|
||||
c-41.4,0-75,33.6-75,75"/>
|
||||
<path class="st0" d="M185,260L185,260v-75c0-41.4,33.6-75,75-75"/>
|
||||
<path class="st0" d="M290,110L290,110v150"/>
|
||||
<path class="st0" d="M470,185c0-41.4-33.6-75-75-75l0,0c-41.4,0-75,33.6-75,75l0,0c0,41.4,33.6,75,75,75l0,0
|
||||
C436.4,260,470,226.4,470,185L470,185V5"/>
|
||||
<path class="st0" d="M650,185c0,41.4-33.6,75-75,75l0,0c-41.4,0-75-33.6-75-75s33.6-75,75-75S650,143.6,650,185L650,185v180
|
||||
c0,41.4-33.6,75-75,75l0,0c-41.4,0-75-33.6-75-75"/>
|
||||
<path class="st0" d="M680,185L680,185h150c0-41.4-33.6-75-75-75S680,143.6,680,185L680,185c0,41.4,33.6,75,75,75"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src-angular/assets/images/placeholder.jpg
Normal file
|
After Width: | Height: | Size: 389 KiB |
BIN
src-angular/assets/images/system/icon.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
src-angular/assets/images/system/icons/mac/icon.icns
Normal file
BIN
src-angular/assets/images/system/icons/png/1024x1024.png
Normal file
|
After Width: | Height: | Size: 194 KiB |
BIN
src-angular/assets/images/system/icons/png/128x128.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src-angular/assets/images/system/icons/png/16x16.png
Normal file
|
After Width: | Height: | Size: 794 B |
BIN
src-angular/assets/images/system/icons/png/24x24.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src-angular/assets/images/system/icons/png/256x256.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
src-angular/assets/images/system/icons/png/32x32.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
src-angular/assets/images/system/icons/png/48x48.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src-angular/assets/images/system/icons/png/512x512.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
src-angular/assets/images/system/icons/png/64x64.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
src-angular/assets/images/system/icons/win/icon.ico
Normal file
|
After Width: | Height: | Size: 353 KiB |
247
src-angular/assets/semantic/dist/components/accordion.css
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Accordion
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Accordion
|
||||
*******************************/
|
||||
|
||||
.ui.accordion,
|
||||
.ui.accordion .accordion {
|
||||
max-width: 100%;
|
||||
}
|
||||
.ui.accordion .accordion {
|
||||
margin: 1em 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Title */
|
||||
.ui.accordion .title,
|
||||
.ui.accordion .accordion .title {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Default Styling */
|
||||
.ui.accordion .title:not(.ui) {
|
||||
padding: 0.5em 0;
|
||||
font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;
|
||||
font-size: 1em;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
|
||||
/* Default Styling */
|
||||
.ui.accordion:not(.styled) .title ~ .content:not(.ui),
|
||||
.ui.accordion:not(.styled) .accordion .title ~ .content:not(.ui) {
|
||||
margin: '';
|
||||
padding: 0.5em 0 1em;
|
||||
}
|
||||
.ui.accordion:not(.styled) .title ~ .content:not(.ui):last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* Arrow */
|
||||
.ui.accordion .title .dropdown.icon,
|
||||
.ui.accordion .accordion .title .dropdown.icon {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
opacity: 1;
|
||||
width: 1.25em;
|
||||
height: 1em;
|
||||
margin: 0 0.25rem 0 0;
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
-webkit-transition: opacity 0.1s ease, -webkit-transform 0.1s ease;
|
||||
transition: opacity 0.1s ease, -webkit-transform 0.1s ease;
|
||||
transition: transform 0.1s ease, opacity 0.1s ease;
|
||||
transition: transform 0.1s ease, opacity 0.1s ease, -webkit-transform 0.1s ease;
|
||||
vertical-align: baseline;
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Coupling
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Menu */
|
||||
.ui.accordion.menu .item .title {
|
||||
display: block;
|
||||
padding: 0;
|
||||
}
|
||||
.ui.accordion.menu .item .title > .dropdown.icon {
|
||||
float: right;
|
||||
margin: 0.21425em 0 0 1em;
|
||||
-webkit-transform: rotate(180deg);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.ui.accordion .ui.header .dropdown.icon {
|
||||
font-size: 1em;
|
||||
margin: 0 0.25rem 0 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
States
|
||||
*******************************/
|
||||
|
||||
.ui.accordion .active.title .dropdown.icon,
|
||||
.ui.accordion .accordion .active.title .dropdown.icon {
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.ui.accordion.menu .item .active.title > .dropdown.icon {
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Types
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Styled
|
||||
---------------*/
|
||||
|
||||
.ui.styled.accordion {
|
||||
width: 600px;
|
||||
}
|
||||
.ui.styled.accordion,
|
||||
.ui.styled.accordion .accordion {
|
||||
border-radius: 0.28571429rem;
|
||||
background: #FFFFFF;
|
||||
-webkit-box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15);
|
||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15);
|
||||
}
|
||||
.ui.styled.accordion .title,
|
||||
.ui.styled.accordion .accordion .title {
|
||||
margin: 0;
|
||||
padding: 0.75em 1em;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
font-weight: bold;
|
||||
border-top: 1px solid rgba(34, 36, 38, 0.15);
|
||||
-webkit-transition: background 0.1s ease, color 0.1s ease;
|
||||
transition: background 0.1s ease, color 0.1s ease;
|
||||
}
|
||||
.ui.styled.accordion > .title:first-child,
|
||||
.ui.styled.accordion .accordion .title:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
/* Content */
|
||||
.ui.styled.accordion .content,
|
||||
.ui.styled.accordion .accordion .content {
|
||||
margin: 0;
|
||||
padding: 0.5em 1em 1.5em;
|
||||
}
|
||||
.ui.styled.accordion .accordion .content {
|
||||
margin: 0;
|
||||
padding: 0.5em 1em 1.5em;
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
.ui.styled.accordion .title:hover,
|
||||
.ui.styled.accordion .active.title,
|
||||
.ui.styled.accordion .accordion .title:hover,
|
||||
.ui.styled.accordion .accordion .active.title {
|
||||
background: transparent;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.ui.styled.accordion .accordion .title:hover,
|
||||
.ui.styled.accordion .accordion .active.title {
|
||||
background: transparent;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
|
||||
/* Active */
|
||||
.ui.styled.accordion .active.title {
|
||||
background: transparent;
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
.ui.styled.accordion .accordion .active.title {
|
||||
background: transparent;
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
States
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Not Active
|
||||
---------------*/
|
||||
|
||||
.ui.accordion .title ~ .content:not(.active),
|
||||
.ui.accordion .accordion .title ~ .content:not(.active) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Variations
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Fluid
|
||||
---------------*/
|
||||
|
||||
.ui.fluid.accordion,
|
||||
.ui.fluid.accordion .accordion {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Inverted
|
||||
---------------*/
|
||||
|
||||
.ui.inverted.accordion .title:not(.ui) {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Accordion';
|
||||
src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMggjB5AAAAC8AAAAYGNtYXAPfOIKAAABHAAAAExnYXNwAAAAEAAAAWgAAAAIZ2x5Zryj6HgAAAFwAAAAyGhlYWT/0IhHAAACOAAAADZoaGVhApkB5wAAAnAAAAAkaG10eAJuABIAAAKUAAAAGGxvY2EAjABWAAACrAAAAA5tYXhwAAgAFgAAArwAAAAgbmFtZfC1n04AAALcAAABPHBvc3QAAwAAAAAEGAAAACAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADw2gHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIPDa//3//wAAAAAAIPDZ//3//wAB/+MPKwADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQASAEkAtwFuABMAADc0PwE2FzYXFh0BFAcGJwYvASY1EgaABQgHBQYGBQcIBYAG2wcGfwcBAQcECf8IBAcBAQd/BgYAAAAAAQAAAEkApQFuABMAADcRNDc2MzIfARYVFA8BBiMiJyY1AAUGBwgFgAYGgAUIBwYFWwEACAUGBoAFCAcFgAYGBQcAAAABAAAAAQAAqWYls18PPPUACwIAAAAAAM/9o+4AAAAAz/2j7gAAAAAAtwFuAAAACAACAAAAAAAAAAEAAAHg/+AAAAIAAAAAAAC3AAEAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAQAAAAC3ABIAtwAAAAAAAAAKABQAHgBCAGQAAAABAAAABgAUAAEAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADAAAAAEAAAAAAAIADgBAAAEAAAAAAAMADAAiAAEAAAAAAAQADABOAAEAAAAAAAUAFgAMAAEAAAAAAAYABgAuAAEAAAAAAAoANABaAAMAAQQJAAEADAAAAAMAAQQJAAIADgBAAAMAAQQJAAMADAAiAAMAAQQJAAQADABOAAMAAQQJAAUAFgAMAAMAAQQJAAYADAA0AAMAAQQJAAoANABaAHIAYQB0AGkAbgBnAFYAZQByAHMAaQBvAG4AIAAxAC4AMAByAGEAdABpAG4AZ3JhdGluZwByAGEAdABpAG4AZwBSAGUAZwB1AGwAYQByAHIAYQB0AGkAbgBnAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype'), url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AAASwAAoAAAAABGgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAAAS0AAAEtFpovuE9TLzIAAAIkAAAAYAAAAGAIIweQY21hcAAAAoQAAABMAAAATA984gpnYXNwAAAC0AAAAAgAAAAIAAAAEGhlYWQAAALYAAAANgAAADb/0IhHaGhlYQAAAxAAAAAkAAAAJAKZAedobXR4AAADNAAAABgAAAAYAm4AEm1heHAAAANMAAAABgAAAAYABlAAbmFtZQAAA1QAAAE8AAABPPC1n05wb3N0AAAEkAAAACAAAAAgAAMAAAEABAQAAQEBB3JhdGluZwABAgABADr4HAL4GwP4GAQeCgAZU/+Lix4KABlT/4uLDAeLa/iU+HQFHQAAAHkPHQAAAH4RHQAAAAkdAAABJBIABwEBBw0PERQZHnJhdGluZ3JhdGluZ3UwdTF1MjB1RjBEOXVGMERBAAACAYkABAAGAQEEBwoNVp38lA78lA78lA77lA773Z33bxWLkI2Qj44I9xT3FAWOj5CNkIuQi4+JjoePiI2Gi4YIi/uUBYuGiYeHiIiHh4mGi4aLho2Ijwj7FPcUBYeOiY+LkAgO+92L5hWL95QFi5CNkI6Oj4+PjZCLkIuQiY6HCPcU+xQFj4iNhouGi4aJh4eICPsU+xQFiIeGiYaLhouHjYePiI6Jj4uQCA74lBT4lBWLDAoAAAAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADw2gHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIPDa//3//wAAAAAAIPDZ//3//wAB/+MPKwADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAEAADfYOJZfDzz1AAsCAAAAAADP/aPuAAAAAM/9o+4AAAAAALcBbgAAAAgAAgAAAAAAAAABAAAB4P/gAAACAAAAAAAAtwABAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAEAAAAAtwASALcAAAAAUAAABgAAAAAADgCuAAEAAAAAAAEADAAAAAEAAAAAAAIADgBAAAEAAAAAAAMADAAiAAEAAAAAAAQADABOAAEAAAAAAAUAFgAMAAEAAAAAAAYABgAuAAEAAAAAAAoANABaAAMAAQQJAAEADAAAAAMAAQQJAAIADgBAAAMAAQQJAAMADAAiAAMAAQQJAAQADABOAAMAAQQJAAUAFgAMAAMAAQQJAAYADAA0AAMAAQQJAAoANABaAHIAYQB0AGkAbgBnAFYAZQByAHMAaQBvAG4AIAAxAC4AMAByAGEAdABpAG4AZ3JhdGluZwByAGEAdABpAG4AZwBSAGUAZwB1AGwAYQByAHIAYQB0AGkAbgBnAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* Dropdown Icon */
|
||||
.ui.accordion .title .dropdown.icon,
|
||||
.ui.accordion .accordion .title .dropdown.icon {
|
||||
font-family: Accordion;
|
||||
line-height: 1;
|
||||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
text-align: center;
|
||||
}
|
||||
.ui.accordion .title .dropdown.icon:before,
|
||||
.ui.accordion .accordion .title .dropdown.icon:before {
|
||||
content: '\f0da' /*rtl:'\f0d9'*/;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
User Overrides
|
||||
*******************************/
|
||||
|
||||
618
src-angular/assets/semantic/dist/components/accordion.js
vendored
Normal file
@@ -0,0 +1,618 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Accordion
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
;(function ($, window, document, undefined) {
|
||||
|
||||
'use strict';
|
||||
|
||||
$.isFunction = $.isFunction || function(obj) {
|
||||
return typeof obj === "function" && typeof obj.nodeType !== "number";
|
||||
};
|
||||
|
||||
window = (typeof window != 'undefined' && window.Math == Math)
|
||||
? window
|
||||
: (typeof self != 'undefined' && self.Math == Math)
|
||||
? self
|
||||
: Function('return this')()
|
||||
;
|
||||
|
||||
$.fn.accordion = function(parameters) {
|
||||
var
|
||||
$allModules = $(this),
|
||||
|
||||
time = new Date().getTime(),
|
||||
performance = [],
|
||||
|
||||
query = arguments[0],
|
||||
methodInvoked = (typeof query == 'string'),
|
||||
queryArguments = [].slice.call(arguments, 1),
|
||||
|
||||
returnedValue
|
||||
;
|
||||
$allModules
|
||||
.each(function() {
|
||||
var
|
||||
settings = ( $.isPlainObject(parameters) )
|
||||
? $.extend(true, {}, $.fn.accordion.settings, parameters)
|
||||
: $.extend({}, $.fn.accordion.settings),
|
||||
|
||||
className = settings.className,
|
||||
namespace = settings.namespace,
|
||||
selector = settings.selector,
|
||||
error = settings.error,
|
||||
|
||||
eventNamespace = '.' + namespace,
|
||||
moduleNamespace = 'module-' + namespace,
|
||||
moduleSelector = $allModules.selector || '',
|
||||
|
||||
$module = $(this),
|
||||
$title = $module.find(selector.title),
|
||||
$content = $module.find(selector.content),
|
||||
|
||||
element = this,
|
||||
instance = $module.data(moduleNamespace),
|
||||
observer,
|
||||
module
|
||||
;
|
||||
|
||||
module = {
|
||||
|
||||
initialize: function() {
|
||||
module.debug('Initializing', $module);
|
||||
module.bind.events();
|
||||
if(settings.observeChanges) {
|
||||
module.observeChanges();
|
||||
}
|
||||
module.instantiate();
|
||||
},
|
||||
|
||||
instantiate: function() {
|
||||
instance = module;
|
||||
$module
|
||||
.data(moduleNamespace, module)
|
||||
;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
module.debug('Destroying previous instance', $module);
|
||||
$module
|
||||
.off(eventNamespace)
|
||||
.removeData(moduleNamespace)
|
||||
;
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
$title = $module.find(selector.title);
|
||||
$content = $module.find(selector.content);
|
||||
},
|
||||
|
||||
observeChanges: function() {
|
||||
if('MutationObserver' in window) {
|
||||
observer = new MutationObserver(function(mutations) {
|
||||
module.debug('DOM tree modified, updating selector cache');
|
||||
module.refresh();
|
||||
});
|
||||
observer.observe(element, {
|
||||
childList : true,
|
||||
subtree : true
|
||||
});
|
||||
module.debug('Setting up mutation observer', observer);
|
||||
}
|
||||
},
|
||||
|
||||
bind: {
|
||||
events: function() {
|
||||
module.debug('Binding delegated events');
|
||||
$module
|
||||
.on(settings.on + eventNamespace, selector.trigger, module.event.click)
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
event: {
|
||||
click: function() {
|
||||
module.toggle.call(this);
|
||||
}
|
||||
},
|
||||
|
||||
toggle: function(query) {
|
||||
var
|
||||
$activeTitle = (query !== undefined)
|
||||
? (typeof query === 'number')
|
||||
? $title.eq(query)
|
||||
: $(query).closest(selector.title)
|
||||
: $(this).closest(selector.title),
|
||||
$activeContent = $activeTitle.next($content),
|
||||
isAnimating = $activeContent.hasClass(className.animating),
|
||||
isActive = $activeContent.hasClass(className.active),
|
||||
isOpen = (isActive && !isAnimating),
|
||||
isOpening = (!isActive && isAnimating)
|
||||
;
|
||||
module.debug('Toggling visibility of content', $activeTitle);
|
||||
if(isOpen || isOpening) {
|
||||
if(settings.collapsible) {
|
||||
module.close.call($activeTitle);
|
||||
}
|
||||
else {
|
||||
module.debug('Cannot close accordion content collapsing is disabled');
|
||||
}
|
||||
}
|
||||
else {
|
||||
module.open.call($activeTitle);
|
||||
}
|
||||
},
|
||||
|
||||
open: function(query) {
|
||||
var
|
||||
$activeTitle = (query !== undefined)
|
||||
? (typeof query === 'number')
|
||||
? $title.eq(query)
|
||||
: $(query).closest(selector.title)
|
||||
: $(this).closest(selector.title),
|
||||
$activeContent = $activeTitle.next($content),
|
||||
isAnimating = $activeContent.hasClass(className.animating),
|
||||
isActive = $activeContent.hasClass(className.active),
|
||||
isOpen = (isActive || isAnimating)
|
||||
;
|
||||
if(isOpen) {
|
||||
module.debug('Accordion already open, skipping', $activeContent);
|
||||
return;
|
||||
}
|
||||
module.debug('Opening accordion content', $activeTitle);
|
||||
settings.onOpening.call($activeContent);
|
||||
settings.onChanging.call($activeContent);
|
||||
if(settings.exclusive) {
|
||||
module.closeOthers.call($activeTitle);
|
||||
}
|
||||
$activeTitle
|
||||
.addClass(className.active)
|
||||
;
|
||||
$activeContent
|
||||
.stop(true, true)
|
||||
.addClass(className.animating)
|
||||
;
|
||||
if(settings.animateChildren) {
|
||||
if($.fn.transition !== undefined && $module.transition('is supported')) {
|
||||
$activeContent
|
||||
.children()
|
||||
.transition({
|
||||
animation : 'fade in',
|
||||
queue : false,
|
||||
useFailSafe : true,
|
||||
debug : settings.debug,
|
||||
verbose : settings.verbose,
|
||||
duration : settings.duration,
|
||||
skipInlineHidden : true,
|
||||
onComplete: function() {
|
||||
$activeContent.children().removeClass(className.transition);
|
||||
}
|
||||
})
|
||||
;
|
||||
}
|
||||
else {
|
||||
$activeContent
|
||||
.children()
|
||||
.stop(true, true)
|
||||
.animate({
|
||||
opacity: 1
|
||||
}, settings.duration, module.resetOpacity)
|
||||
;
|
||||
}
|
||||
}
|
||||
$activeContent
|
||||
.slideDown(settings.duration, settings.easing, function() {
|
||||
$activeContent
|
||||
.removeClass(className.animating)
|
||||
.addClass(className.active)
|
||||
;
|
||||
module.reset.display.call(this);
|
||||
settings.onOpen.call(this);
|
||||
settings.onChange.call(this);
|
||||
})
|
||||
;
|
||||
},
|
||||
|
||||
close: function(query) {
|
||||
var
|
||||
$activeTitle = (query !== undefined)
|
||||
? (typeof query === 'number')
|
||||
? $title.eq(query)
|
||||
: $(query).closest(selector.title)
|
||||
: $(this).closest(selector.title),
|
||||
$activeContent = $activeTitle.next($content),
|
||||
isAnimating = $activeContent.hasClass(className.animating),
|
||||
isActive = $activeContent.hasClass(className.active),
|
||||
isOpening = (!isActive && isAnimating),
|
||||
isClosing = (isActive && isAnimating)
|
||||
;
|
||||
if((isActive || isOpening) && !isClosing) {
|
||||
module.debug('Closing accordion content', $activeContent);
|
||||
settings.onClosing.call($activeContent);
|
||||
settings.onChanging.call($activeContent);
|
||||
$activeTitle
|
||||
.removeClass(className.active)
|
||||
;
|
||||
$activeContent
|
||||
.stop(true, true)
|
||||
.addClass(className.animating)
|
||||
;
|
||||
if(settings.animateChildren) {
|
||||
if($.fn.transition !== undefined && $module.transition('is supported')) {
|
||||
$activeContent
|
||||
.children()
|
||||
.transition({
|
||||
animation : 'fade out',
|
||||
queue : false,
|
||||
useFailSafe : true,
|
||||
debug : settings.debug,
|
||||
verbose : settings.verbose,
|
||||
duration : settings.duration,
|
||||
skipInlineHidden : true
|
||||
})
|
||||
;
|
||||
}
|
||||
else {
|
||||
$activeContent
|
||||
.children()
|
||||
.stop(true, true)
|
||||
.animate({
|
||||
opacity: 0
|
||||
}, settings.duration, module.resetOpacity)
|
||||
;
|
||||
}
|
||||
}
|
||||
$activeContent
|
||||
.slideUp(settings.duration, settings.easing, function() {
|
||||
$activeContent
|
||||
.removeClass(className.animating)
|
||||
.removeClass(className.active)
|
||||
;
|
||||
module.reset.display.call(this);
|
||||
settings.onClose.call(this);
|
||||
settings.onChange.call(this);
|
||||
})
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
closeOthers: function(index) {
|
||||
var
|
||||
$activeTitle = (index !== undefined)
|
||||
? $title.eq(index)
|
||||
: $(this).closest(selector.title),
|
||||
$parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
|
||||
$activeAccordion = $activeTitle.closest(selector.accordion),
|
||||
activeSelector = selector.title + '.' + className.active + ':visible',
|
||||
activeContent = selector.content + '.' + className.active + ':visible',
|
||||
$openTitles,
|
||||
$nestedTitles,
|
||||
$openContents
|
||||
;
|
||||
if(settings.closeNested) {
|
||||
$openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
|
||||
$openContents = $openTitles.next($content);
|
||||
}
|
||||
else {
|
||||
$openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
|
||||
$nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
|
||||
$openTitles = $openTitles.not($nestedTitles);
|
||||
$openContents = $openTitles.next($content);
|
||||
}
|
||||
if( ($openTitles.length > 0) ) {
|
||||
module.debug('Exclusive enabled, closing other content', $openTitles);
|
||||
$openTitles
|
||||
.removeClass(className.active)
|
||||
;
|
||||
$openContents
|
||||
.removeClass(className.animating)
|
||||
.stop(true, true)
|
||||
;
|
||||
if(settings.animateChildren) {
|
||||
if($.fn.transition !== undefined && $module.transition('is supported')) {
|
||||
$openContents
|
||||
.children()
|
||||
.transition({
|
||||
animation : 'fade out',
|
||||
useFailSafe : true,
|
||||
debug : settings.debug,
|
||||
verbose : settings.verbose,
|
||||
duration : settings.duration,
|
||||
skipInlineHidden : true
|
||||
})
|
||||
;
|
||||
}
|
||||
else {
|
||||
$openContents
|
||||
.children()
|
||||
.stop(true, true)
|
||||
.animate({
|
||||
opacity: 0
|
||||
}, settings.duration, module.resetOpacity)
|
||||
;
|
||||
}
|
||||
}
|
||||
$openContents
|
||||
.slideUp(settings.duration , settings.easing, function() {
|
||||
$(this).removeClass(className.active);
|
||||
module.reset.display.call(this);
|
||||
})
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
reset: {
|
||||
|
||||
display: function() {
|
||||
module.verbose('Removing inline display from element', this);
|
||||
$(this).css('display', '');
|
||||
if( $(this).attr('style') === '') {
|
||||
$(this)
|
||||
.attr('style', '')
|
||||
.removeAttr('style')
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
opacity: function() {
|
||||
module.verbose('Removing inline opacity from element', this);
|
||||
$(this).css('opacity', '');
|
||||
if( $(this).attr('style') === '') {
|
||||
$(this)
|
||||
.attr('style', '')
|
||||
.removeAttr('style')
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
setting: function(name, value) {
|
||||
module.debug('Changing setting', name, value);
|
||||
if( $.isPlainObject(name) ) {
|
||||
$.extend(true, settings, name);
|
||||
}
|
||||
else if(value !== undefined) {
|
||||
if($.isPlainObject(settings[name])) {
|
||||
$.extend(true, settings[name], value);
|
||||
}
|
||||
else {
|
||||
settings[name] = value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return settings[name];
|
||||
}
|
||||
},
|
||||
internal: function(name, value) {
|
||||
module.debug('Changing internal', name, value);
|
||||
if(value !== undefined) {
|
||||
if( $.isPlainObject(name) ) {
|
||||
$.extend(true, module, name);
|
||||
}
|
||||
else {
|
||||
module[name] = value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return module[name];
|
||||
}
|
||||
},
|
||||
debug: function() {
|
||||
if(!settings.silent && settings.debug) {
|
||||
if(settings.performance) {
|
||||
module.performance.log(arguments);
|
||||
}
|
||||
else {
|
||||
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
||||
module.debug.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
},
|
||||
verbose: function() {
|
||||
if(!settings.silent && settings.verbose && settings.debug) {
|
||||
if(settings.performance) {
|
||||
module.performance.log(arguments);
|
||||
}
|
||||
else {
|
||||
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
||||
module.verbose.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
if(!settings.silent) {
|
||||
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
|
||||
module.error.apply(console, arguments);
|
||||
}
|
||||
},
|
||||
performance: {
|
||||
log: function(message) {
|
||||
var
|
||||
currentTime,
|
||||
executionTime,
|
||||
previousTime
|
||||
;
|
||||
if(settings.performance) {
|
||||
currentTime = new Date().getTime();
|
||||
previousTime = time || currentTime;
|
||||
executionTime = currentTime - previousTime;
|
||||
time = currentTime;
|
||||
performance.push({
|
||||
'Name' : message[0],
|
||||
'Arguments' : [].slice.call(message, 1) || '',
|
||||
'Element' : element,
|
||||
'Execution Time' : executionTime
|
||||
});
|
||||
}
|
||||
clearTimeout(module.performance.timer);
|
||||
module.performance.timer = setTimeout(module.performance.display, 500);
|
||||
},
|
||||
display: function() {
|
||||
var
|
||||
title = settings.name + ':',
|
||||
totalTime = 0
|
||||
;
|
||||
time = false;
|
||||
clearTimeout(module.performance.timer);
|
||||
$.each(performance, function(index, data) {
|
||||
totalTime += data['Execution Time'];
|
||||
});
|
||||
title += ' ' + totalTime + 'ms';
|
||||
if(moduleSelector) {
|
||||
title += ' \'' + moduleSelector + '\'';
|
||||
}
|
||||
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
|
||||
console.groupCollapsed(title);
|
||||
if(console.table) {
|
||||
console.table(performance);
|
||||
}
|
||||
else {
|
||||
$.each(performance, function(index, data) {
|
||||
console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
|
||||
});
|
||||
}
|
||||
console.groupEnd();
|
||||
}
|
||||
performance = [];
|
||||
}
|
||||
},
|
||||
invoke: function(query, passedArguments, context) {
|
||||
var
|
||||
object = instance,
|
||||
maxDepth,
|
||||
found,
|
||||
response
|
||||
;
|
||||
passedArguments = passedArguments || queryArguments;
|
||||
context = element || context;
|
||||
if(typeof query == 'string' && object !== undefined) {
|
||||
query = query.split(/[\. ]/);
|
||||
maxDepth = query.length - 1;
|
||||
$.each(query, function(depth, value) {
|
||||
var camelCaseValue = (depth != maxDepth)
|
||||
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
|
||||
: query
|
||||
;
|
||||
if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
|
||||
object = object[camelCaseValue];
|
||||
}
|
||||
else if( object[camelCaseValue] !== undefined ) {
|
||||
found = object[camelCaseValue];
|
||||
return false;
|
||||
}
|
||||
else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
|
||||
object = object[value];
|
||||
}
|
||||
else if( object[value] !== undefined ) {
|
||||
found = object[value];
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
module.error(error.method, query);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
if ( $.isFunction( found ) ) {
|
||||
response = found.apply(context, passedArguments);
|
||||
}
|
||||
else if(found !== undefined) {
|
||||
response = found;
|
||||
}
|
||||
if(Array.isArray(returnedValue)) {
|
||||
returnedValue.push(response);
|
||||
}
|
||||
else if(returnedValue !== undefined) {
|
||||
returnedValue = [returnedValue, response];
|
||||
}
|
||||
else if(response !== undefined) {
|
||||
returnedValue = response;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
};
|
||||
if(methodInvoked) {
|
||||
if(instance === undefined) {
|
||||
module.initialize();
|
||||
}
|
||||
module.invoke(query);
|
||||
}
|
||||
else {
|
||||
if(instance !== undefined) {
|
||||
instance.invoke('destroy');
|
||||
}
|
||||
module.initialize();
|
||||
}
|
||||
})
|
||||
;
|
||||
return (returnedValue !== undefined)
|
||||
? returnedValue
|
||||
: this
|
||||
;
|
||||
};
|
||||
|
||||
$.fn.accordion.settings = {
|
||||
|
||||
name : 'Accordion',
|
||||
namespace : 'accordion',
|
||||
|
||||
silent : false,
|
||||
debug : false,
|
||||
verbose : false,
|
||||
performance : true,
|
||||
|
||||
on : 'click', // event on title that opens accordion
|
||||
|
||||
observeChanges : true, // whether accordion should automatically refresh on DOM insertion
|
||||
|
||||
exclusive : true, // whether a single accordion content panel should be open at once
|
||||
collapsible : true, // whether accordion content can be closed
|
||||
closeNested : false, // whether nested content should be closed when a panel is closed
|
||||
animateChildren : true, // whether children opacity should be animated
|
||||
|
||||
duration : 350, // duration of animation
|
||||
easing : 'easeOutQuad', // easing equation for animation
|
||||
|
||||
onOpening : function(){}, // callback before open animation
|
||||
onClosing : function(){}, // callback before closing animation
|
||||
onChanging : function(){}, // callback before closing or opening animation
|
||||
|
||||
onOpen : function(){}, // callback after open animation
|
||||
onClose : function(){}, // callback after closing animation
|
||||
onChange : function(){}, // callback after closing or opening animation
|
||||
|
||||
error: {
|
||||
method : 'The method you called is not defined'
|
||||
},
|
||||
|
||||
className : {
|
||||
active : 'active',
|
||||
animating : 'animating',
|
||||
transition: 'transition'
|
||||
},
|
||||
|
||||
selector : {
|
||||
accordion : '.accordion',
|
||||
title : '.title',
|
||||
trigger : '.title',
|
||||
content : '.content'
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Adds easing
|
||||
$.extend( $.easing, {
|
||||
easeOutQuad: function (x, t, b, c, d) {
|
||||
return -c *(t/=d)*(t-2) + b;
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery, window, document );
|
||||
|
||||
9
src-angular/assets/semantic/dist/components/accordion.min.css
vendored
Normal file
11
src-angular/assets/semantic/dist/components/accordion.min.js
vendored
Normal file
275
src-angular/assets/semantic/dist/components/ad.css
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Ad
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Copyright 2013 Contributors
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Advertisement
|
||||
*******************************/
|
||||
|
||||
.ui.ad {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 1em 0;
|
||||
}
|
||||
.ui.ad:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
.ui.ad:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
.ui.ad iframe {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Common
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Leaderboard */
|
||||
.ui.leaderboard.ad {
|
||||
width: 728px;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
/* Medium Rectangle */
|
||||
.ui[class*="medium rectangle"].ad {
|
||||
width: 300px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
/* Large Rectangle */
|
||||
.ui[class*="large rectangle"].ad {
|
||||
width: 336px;
|
||||
height: 280px;
|
||||
}
|
||||
|
||||
/* Half Page */
|
||||
.ui[class*="half page"].ad {
|
||||
width: 300px;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Square
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Square */
|
||||
.ui.square.ad {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
/* Small Square */
|
||||
.ui[class*="small square"].ad {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Rectangle
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Small Rectangle */
|
||||
.ui[class*="small rectangle"].ad {
|
||||
width: 180px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
/* Vertical Rectangle */
|
||||
.ui[class*="vertical rectangle"].ad {
|
||||
width: 240px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Button
|
||||
---------------*/
|
||||
|
||||
.ui.button.ad {
|
||||
width: 120px;
|
||||
height: 90px;
|
||||
}
|
||||
.ui[class*="square button"].ad {
|
||||
width: 125px;
|
||||
height: 125px;
|
||||
}
|
||||
.ui[class*="small button"].ad {
|
||||
width: 120px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Skyscrapers
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Skyscraper */
|
||||
.ui.skyscraper.ad {
|
||||
width: 120px;
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
/* Wide Skyscraper */
|
||||
.ui[class*="wide skyscraper"].ad {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Banners
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Banner */
|
||||
.ui.banner.ad {
|
||||
width: 468px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
/* Vertical Banner */
|
||||
.ui[class*="vertical banner"].ad {
|
||||
width: 120px;
|
||||
height: 240px;
|
||||
}
|
||||
|
||||
/* Top Banner */
|
||||
.ui[class*="top banner"].ad {
|
||||
width: 930px;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
/* Half Banner */
|
||||
.ui[class*="half banner"].ad {
|
||||
width: 234px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Boards
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Leaderboard */
|
||||
.ui[class*="large leaderboard"].ad {
|
||||
width: 970px;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
/* Billboard */
|
||||
.ui.billboard.ad {
|
||||
width: 970px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Panorama
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Panorama */
|
||||
.ui.panorama.ad {
|
||||
width: 980px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Netboard
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Netboard */
|
||||
.ui.netboard.ad {
|
||||
width: 580px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Mobile
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Large Mobile Banner */
|
||||
.ui[class*="large mobile banner"].ad {
|
||||
width: 320px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
/* Mobile Leaderboard */
|
||||
.ui[class*="mobile leaderboard"].ad {
|
||||
width: 320px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Types
|
||||
*******************************/
|
||||
|
||||
|
||||
/* Mobile Sizes */
|
||||
.ui.mobile.ad {
|
||||
display: none;
|
||||
}
|
||||
@media only screen and (max-width: 767.98px) {
|
||||
.ui.mobile.ad {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Variations
|
||||
*******************************/
|
||||
|
||||
.ui.centered.ad {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.ui.test.ad {
|
||||
position: relative;
|
||||
background: #545454;
|
||||
}
|
||||
.ui.test.ad:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
-webkit-transform: translateX(-50%) translateY(-50%);
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
content: 'Ad';
|
||||
color: #FFFFFF;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui.mobile.test.ad:after {
|
||||
font-size: 0.85714286em;
|
||||
}
|
||||
.ui.test.ad[data-text]:after {
|
||||
content: attr(data-text);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
User Variable Overrides
|
||||
*******************************/
|
||||
|
||||
10
src-angular/assets/semantic/dist/components/ad.min.css
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Ad
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Copyright 2013 Contributors
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/.ui.ad{display:block;overflow:hidden;margin:1em 0}.ui.ad:first-child{margin:0}.ui.ad:last-child{margin:0}.ui.ad iframe{margin:0;padding:0;border:none;overflow:hidden}.ui.leaderboard.ad{width:728px;height:90px}.ui[class*="medium rectangle"].ad{width:300px;height:250px}.ui[class*="large rectangle"].ad{width:336px;height:280px}.ui[class*="half page"].ad{width:300px;height:600px}.ui.square.ad{width:250px;height:250px}.ui[class*="small square"].ad{width:200px;height:200px}.ui[class*="small rectangle"].ad{width:180px;height:150px}.ui[class*="vertical rectangle"].ad{width:240px;height:400px}.ui.button.ad{width:120px;height:90px}.ui[class*="square button"].ad{width:125px;height:125px}.ui[class*="small button"].ad{width:120px;height:60px}.ui.skyscraper.ad{width:120px;height:600px}.ui[class*="wide skyscraper"].ad{width:160px}.ui.banner.ad{width:468px;height:60px}.ui[class*="vertical banner"].ad{width:120px;height:240px}.ui[class*="top banner"].ad{width:930px;height:180px}.ui[class*="half banner"].ad{width:234px;height:60px}.ui[class*="large leaderboard"].ad{width:970px;height:90px}.ui.billboard.ad{width:970px;height:250px}.ui.panorama.ad{width:980px;height:120px}.ui.netboard.ad{width:580px;height:400px}.ui[class*="large mobile banner"].ad{width:320px;height:100px}.ui[class*="mobile leaderboard"].ad{width:320px;height:50px}.ui.mobile.ad{display:none}@media only screen and (max-width:767.98px){.ui.mobile.ad{display:block}}.ui.centered.ad{margin-left:auto;margin-right:auto}.ui.test.ad{position:relative;background:#545454}.ui.test.ad:after{position:absolute;top:50%;left:50%;width:100%;text-align:center;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);content:'Ad';color:#fff;font-size:1em;font-weight:700}.ui.mobile.test.ad:after{font-size:.85714286em}.ui.test.ad[data-text]:after{content:attr(data-text)}
|
||||
1177
src-angular/assets/semantic/dist/components/api.js
vendored
Normal file
11
src-angular/assets/semantic/dist/components/api.min.js
vendored
Normal file
135
src-angular/assets/semantic/dist/components/breadcrumb.css
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Breadcrumb
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Breadcrumb
|
||||
*******************************/
|
||||
|
||||
.ui.breadcrumb {
|
||||
line-height: 1.4285em;
|
||||
display: inline-block;
|
||||
margin: 0 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.ui.breadcrumb:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui.breadcrumb:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Content
|
||||
*******************************/
|
||||
|
||||
|
||||
/* Divider */
|
||||
.ui.breadcrumb .divider {
|
||||
display: inline-block;
|
||||
opacity: 0.7;
|
||||
margin: 0 0.21428571rem 0;
|
||||
font-size: 0.92857143em;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* Link */
|
||||
.ui.breadcrumb a {
|
||||
color: #4183C4;
|
||||
}
|
||||
.ui.breadcrumb a:hover {
|
||||
color: #1e70bf;
|
||||
}
|
||||
|
||||
/* Icon Divider */
|
||||
.ui.breadcrumb .icon.divider {
|
||||
font-size: 0.85714286em;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* Section */
|
||||
.ui.breadcrumb a.section {
|
||||
cursor: pointer;
|
||||
}
|
||||
.ui.breadcrumb .section {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Loose Coupling */
|
||||
.ui.breadcrumb.segment {
|
||||
display: inline-block;
|
||||
padding: 0.78571429em 1em;
|
||||
}
|
||||
|
||||
/* Inverted */
|
||||
.ui.inverted.breadcrumb {
|
||||
color: #DCDDDE;
|
||||
}
|
||||
.ui.inverted.breadcrumb > .active.section {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.ui.inverted.breadcrumb > .divider {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
States
|
||||
*******************************/
|
||||
|
||||
.ui.breadcrumb .active.section {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Variations
|
||||
*******************************/
|
||||
|
||||
.ui.breadcrumb {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.ui.mini.breadcrumb {
|
||||
font-size: 0.78571429rem;
|
||||
}
|
||||
.ui.tiny.breadcrumb {
|
||||
font-size: 0.85714286rem;
|
||||
}
|
||||
.ui.small.breadcrumb {
|
||||
font-size: 0.92857143rem;
|
||||
}
|
||||
.ui.large.breadcrumb {
|
||||
font-size: 1.14285714rem;
|
||||
}
|
||||
.ui.big.breadcrumb {
|
||||
font-size: 1.28571429rem;
|
||||
}
|
||||
.ui.huge.breadcrumb {
|
||||
font-size: 1.42857143rem;
|
||||
}
|
||||
.ui.massive.breadcrumb {
|
||||
font-size: 1.71428571rem;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
Site Overrides
|
||||
*******************************/
|
||||
|
||||
9
src-angular/assets/semantic/dist/components/breadcrumb.min.css
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Breadcrumb
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/.ui.breadcrumb{line-height:1.4285em;display:inline-block;margin:0 0;vertical-align:middle}.ui.breadcrumb:first-child{margin-top:0}.ui.breadcrumb:last-child{margin-bottom:0}.ui.breadcrumb .divider{display:inline-block;opacity:.7;margin:0 .21428571rem 0;font-size:.92857143em;color:rgba(0,0,0,.4);vertical-align:baseline}.ui.breadcrumb a{color:#4183c4}.ui.breadcrumb a:hover{color:#1e70bf}.ui.breadcrumb .icon.divider{font-size:.85714286em;vertical-align:baseline}.ui.breadcrumb a.section{cursor:pointer}.ui.breadcrumb .section{display:inline-block;margin:0;padding:0}.ui.breadcrumb.segment{display:inline-block;padding:.78571429em 1em}.ui.inverted.breadcrumb{color:#dcddde}.ui.inverted.breadcrumb>.active.section{color:#fff}.ui.inverted.breadcrumb>.divider{color:rgba(255,255,255,.7)}.ui.breadcrumb .active.section{font-weight:700}.ui.breadcrumb{font-size:1rem}.ui.mini.breadcrumb{font-size:.78571429rem}.ui.tiny.breadcrumb{font-size:.85714286rem}.ui.small.breadcrumb{font-size:.92857143rem}.ui.large.breadcrumb{font-size:1.14285714rem}.ui.big.breadcrumb{font-size:1.28571429rem}.ui.huge.breadcrumb{font-size:1.42857143rem}.ui.massive.breadcrumb{font-size:1.71428571rem}
|
||||
4372
src-angular/assets/semantic/dist/components/button.css
vendored
Normal file
9
src-angular/assets/semantic/dist/components/button.min.css
vendored
Normal file
169
src-angular/assets/semantic/dist/components/calendar.css
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Calendar
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Popup
|
||||
*******************************/
|
||||
|
||||
.ui.calendar .ui.popup {
|
||||
max-width: none;
|
||||
padding: 0;
|
||||
border: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Calendar
|
||||
*******************************/
|
||||
|
||||
.ui.calendar .calendar:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Grid
|
||||
*******************************/
|
||||
|
||||
.ui.calendar .ui.popup .ui.grid {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ui.calendar .ui.popup .ui.grid > .column {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Table
|
||||
*******************************/
|
||||
|
||||
.ui.calendar .ui.table.year,
|
||||
.ui.calendar .ui.table.month,
|
||||
.ui.calendar .ui.table.minute {
|
||||
min-width: 15em;
|
||||
}
|
||||
.ui.calendar .ui.table.day {
|
||||
min-width: 18em;
|
||||
}
|
||||
.ui.calendar .ui.table.day.andweek {
|
||||
min-width: 22em;
|
||||
}
|
||||
.ui.calendar .ui.table.hour {
|
||||
min-width: 20em;
|
||||
}
|
||||
.ui.calendar .ui.table tr th,
|
||||
.ui.calendar .ui.table tr td {
|
||||
padding: 0.5em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ui.calendar .ui.table tr th {
|
||||
border-left: none;
|
||||
}
|
||||
.ui.calendar .ui.table tr th .icon {
|
||||
margin: 0;
|
||||
}
|
||||
.ui.calendar .ui.table tr:first-child th {
|
||||
position: relative;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.ui.calendar .ui.table.day tr:first-child th {
|
||||
border: none;
|
||||
}
|
||||
.ui.calendar .ui.table.day tr:nth-child(2) th {
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.3em;
|
||||
}
|
||||
.ui.calendar .ui.table tr td {
|
||||
padding-left: 0.1em;
|
||||
padding-right: 0.1em;
|
||||
}
|
||||
.ui.calendar .ui.table tr .link {
|
||||
cursor: pointer;
|
||||
}
|
||||
.ui.calendar .ui.table tr .prev.link {
|
||||
width: 14.28571429%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
.ui.calendar .ui.table tr .next.link {
|
||||
width: 14.28571429%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
.ui.calendar .ui.table tr .disabled {
|
||||
pointer-events: auto;
|
||||
cursor: default;
|
||||
color: rgba(40, 40, 40, 0.3);
|
||||
}
|
||||
.ui.calendar .ui.table tr .adjacent:not(.disabled) {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
States
|
||||
---------------*/
|
||||
|
||||
.ui.calendar .ui.table tr td.today {
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui.calendar .ui.table tr td.range {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.ui.calendar .ui.table.inverted tr td.range {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: #ffffff;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.ui.calendar:not(.disabled) .calendar:focus .ui.table tbody tr td.focus,
|
||||
.ui.calendar:not(.disabled) .calendar.active .ui.table tbody tr td.focus {
|
||||
-webkit-box-shadow: inset 0 0 0 1px #85B7D9;
|
||||
box-shadow: inset 0 0 0 1px #85B7D9;
|
||||
}
|
||||
.ui.calendar:not(.disabled) .calendar:focus .ui.table.inverted tbody tr td.focus,
|
||||
.ui.calendar:not(.disabled) .calendar.active .ui.table.inverted tbody tr td.focus {
|
||||
-webkit-box-shadow: inset 0 0 0 1px #85B7D9;
|
||||
box-shadow: inset 0 0 0 1px #85B7D9;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
States
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------------
|
||||
Disabled
|
||||
---------------------*/
|
||||
|
||||
.ui.disabled.calendar {
|
||||
opacity: 0.45;
|
||||
}
|
||||
.ui.disabled.calendar > .input,
|
||||
.ui.disabled.calendar .ui.table tr .link {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
1585
src-angular/assets/semantic/dist/components/calendar.js
vendored
Normal file
9
src-angular/assets/semantic/dist/components/calendar.min.css
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Calendar
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/.ui.calendar .ui.popup{max-width:none;padding:0;border:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ui.calendar .calendar:focus{outline:0}.ui.calendar .ui.popup .ui.grid{display:block;white-space:nowrap}.ui.calendar .ui.popup .ui.grid>.column{width:auto}.ui.calendar .ui.table.minute,.ui.calendar .ui.table.month,.ui.calendar .ui.table.year{min-width:15em}.ui.calendar .ui.table.day{min-width:18em}.ui.calendar .ui.table.day.andweek{min-width:22em}.ui.calendar .ui.table.hour{min-width:20em}.ui.calendar .ui.table tr td,.ui.calendar .ui.table tr th{padding:.5em;white-space:nowrap}.ui.calendar .ui.table tr th{border-left:none}.ui.calendar .ui.table tr th .icon{margin:0}.ui.calendar .ui.table tr:first-child th{position:relative;padding-left:0;padding-right:0}.ui.calendar .ui.table.day tr:first-child th{border:none}.ui.calendar .ui.table.day tr:nth-child(2) th{padding-top:.2em;padding-bottom:.3em}.ui.calendar .ui.table tr td{padding-left:.1em;padding-right:.1em}.ui.calendar .ui.table tr .link{cursor:pointer}.ui.calendar .ui.table tr .prev.link{width:14.28571429%;position:absolute;left:0}.ui.calendar .ui.table tr .next.link{width:14.28571429%;position:absolute;right:0}.ui.calendar .ui.table tr .disabled{pointer-events:auto;cursor:default;color:rgba(40,40,40,.3)}.ui.calendar .ui.table tr .adjacent:not(.disabled){color:rgba(0,0,0,.6);background:rgba(0,0,0,.03)}.ui.calendar .ui.table tr td.today{font-weight:700}.ui.calendar .ui.table tr td.range{background:rgba(0,0,0,.05);color:rgba(0,0,0,.95);-webkit-box-shadow:none;box-shadow:none}.ui.calendar .ui.table.inverted tr td.range{background:rgba(255,255,255,.08);color:#fff;-webkit-box-shadow:none;box-shadow:none}.ui.calendar:not(.disabled) .calendar.active .ui.table tbody tr td.focus,.ui.calendar:not(.disabled) .calendar:focus .ui.table tbody tr td.focus{-webkit-box-shadow:inset 0 0 0 1px #85b7d9;box-shadow:inset 0 0 0 1px #85b7d9}.ui.calendar:not(.disabled) .calendar.active .ui.table.inverted tbody tr td.focus,.ui.calendar:not(.disabled) .calendar:focus .ui.table.inverted tbody tr td.focus{-webkit-box-shadow:inset 0 0 0 1px #85b7d9;box-shadow:inset 0 0 0 1px #85b7d9}.ui.disabled.calendar{opacity:.45}.ui.disabled.calendar .ui.table tr .link,.ui.disabled.calendar>.input{pointer-events:none}
|
||||
11
src-angular/assets/semantic/dist/components/calendar.min.js
vendored
Normal file
1318
src-angular/assets/semantic/dist/components/card.css
vendored
Normal file
9
src-angular/assets/semantic/dist/components/card.min.css
vendored
Normal file
768
src-angular/assets/semantic/dist/components/checkbox.css
vendored
Normal file
@@ -0,0 +1,768 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Checkbox
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Checkbox
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Content
|
||||
---------------*/
|
||||
|
||||
.ui.checkbox {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
outline: none;
|
||||
vertical-align: baseline;
|
||||
font-style: normal;
|
||||
min-height: 17px;
|
||||
font-size: 1em;
|
||||
line-height: 17px;
|
||||
min-width: 17px;
|
||||
}
|
||||
|
||||
/* HTML Checkbox */
|
||||
.ui.checkbox input[type="checkbox"],
|
||||
.ui.checkbox input[type="radio"] {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0 !important;
|
||||
outline: none;
|
||||
z-index: 3;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
}
|
||||
.ui.checkbox label {
|
||||
cursor: auto;
|
||||
position: relative;
|
||||
display: block;
|
||||
padding-left: 1.85714em;
|
||||
outline: none;
|
||||
font-size: 1em;
|
||||
}
|
||||
.ui.checkbox label:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
content: '';
|
||||
background: #FFFFFF;
|
||||
border-radius: 0.21428571rem;
|
||||
-webkit-transition: border 0.1s ease, opacity 0.1s ease, -webkit-transform 0.1s ease, -webkit-box-shadow 0.1s ease;
|
||||
transition: border 0.1s ease, opacity 0.1s ease, -webkit-transform 0.1s ease, -webkit-box-shadow 0.1s ease;
|
||||
transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease;
|
||||
transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease, -webkit-transform 0.1s ease, -webkit-box-shadow 0.1s ease;
|
||||
border: 1px solid #D4D4D5;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Checkmark
|
||||
---------------*/
|
||||
|
||||
.ui.checkbox label:after {
|
||||
position: absolute;
|
||||
font-size: 14px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
-webkit-transition: border 0.1s ease, opacity 0.1s ease, -webkit-transform 0.1s ease, -webkit-box-shadow 0.1s ease;
|
||||
transition: border 0.1s ease, opacity 0.1s ease, -webkit-transform 0.1s ease, -webkit-box-shadow 0.1s ease;
|
||||
transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease;
|
||||
transition: border 0.1s ease, opacity 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease, -webkit-transform 0.1s ease, -webkit-box-shadow 0.1s ease;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Label
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Inside */
|
||||
.ui.checkbox label,
|
||||
.ui.checkbox + label {
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
-webkit-transition: color 0.1s ease;
|
||||
transition: color 0.1s ease;
|
||||
}
|
||||
|
||||
/* Outside */
|
||||
.ui.checkbox + label {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
States
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Hover
|
||||
---------------*/
|
||||
|
||||
.ui.checkbox label:hover::before {
|
||||
background: #FFFFFF;
|
||||
border-color: rgba(34, 36, 38, 0.35);
|
||||
}
|
||||
.ui.checkbox label:hover,
|
||||
.ui.checkbox + label:hover {
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Down
|
||||
---------------*/
|
||||
|
||||
.ui.checkbox label:active::before {
|
||||
background: #F9FAFB;
|
||||
border-color: rgba(34, 36, 38, 0.35);
|
||||
}
|
||||
.ui.checkbox label:active::after {
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
.ui.checkbox input:active ~ label {
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Focus
|
||||
---------------*/
|
||||
|
||||
.ui.checkbox input:focus ~ label:before {
|
||||
background: #FFFFFF;
|
||||
border-color: #96C8DA;
|
||||
}
|
||||
.ui.checkbox input:focus ~ label:after {
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
.ui.checkbox input:focus ~ label {
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Active
|
||||
---------------*/
|
||||
|
||||
.ui.checkbox input:checked ~ label:before {
|
||||
background: #FFFFFF;
|
||||
border-color: rgba(34, 36, 38, 0.35);
|
||||
}
|
||||
.ui.checkbox input:checked ~ label:after {
|
||||
opacity: 1;
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Indeterminate
|
||||
---------------*/
|
||||
|
||||
.ui.checkbox input:not([type=radio]):indeterminate ~ label:before {
|
||||
background: #FFFFFF;
|
||||
border-color: rgba(34, 36, 38, 0.35);
|
||||
}
|
||||
.ui.checkbox input:not([type=radio]):indeterminate ~ label:after {
|
||||
opacity: 1;
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
.ui.indeterminate.toggle.checkbox input:not([type=radio]):indeterminate ~ label:before {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.ui.indeterminate.toggle.checkbox input:not([type=radio]) ~ label:after {
|
||||
left: 1.075rem;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Active Focus
|
||||
---------------*/
|
||||
|
||||
.ui.checkbox input:not([type=radio]):indeterminate:focus ~ label:before,
|
||||
.ui.checkbox input:checked:focus ~ label:before {
|
||||
background: #FFFFFF;
|
||||
border-color: #96C8DA;
|
||||
}
|
||||
.ui.checkbox input:not([type=radio]):indeterminate:focus ~ label:after,
|
||||
.ui.checkbox input:checked:focus ~ label:after {
|
||||
color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Read-Only
|
||||
---------------*/
|
||||
|
||||
.ui.read-only.checkbox,
|
||||
.ui.read-only.checkbox label {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Disabled
|
||||
---------------*/
|
||||
|
||||
.ui.disabled.checkbox label,
|
||||
.ui.checkbox input[disabled] ~ label {
|
||||
cursor: default !important;
|
||||
opacity: 0.5;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Hidden
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Initialized checkbox moves input below element
|
||||
to prevent manually triggering */
|
||||
.ui.checkbox input.hidden {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* Selectable Label */
|
||||
.ui.checkbox input.hidden + label {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Types
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Radio
|
||||
---------------*/
|
||||
|
||||
.ui.radio.checkbox {
|
||||
min-height: 15px;
|
||||
}
|
||||
.ui.radio.checkbox label {
|
||||
padding-left: 1.85714em;
|
||||
}
|
||||
|
||||
/* Box */
|
||||
.ui.radio.checkbox label:before {
|
||||
content: '';
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 500rem;
|
||||
top: 1px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Bullet */
|
||||
.ui.radio.checkbox label:after {
|
||||
border: none;
|
||||
content: '' !important;
|
||||
line-height: 15px;
|
||||
top: 1px;
|
||||
left: 0;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border-radius: 500rem;
|
||||
-webkit-transform: scale(0.46666667);
|
||||
transform: scale(0.46666667);
|
||||
background-color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
|
||||
/* Focus */
|
||||
.ui.radio.checkbox input:focus ~ label:before {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
.ui.radio.checkbox input:focus ~ label:after {
|
||||
background-color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
/* Indeterminate */
|
||||
.ui.radio.checkbox input:indeterminate ~ label:after {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Active */
|
||||
.ui.radio.checkbox input:checked ~ label:before {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
.ui.radio.checkbox input:checked ~ label:after {
|
||||
background-color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
/* Active Focus */
|
||||
.ui.radio.checkbox input:focus:checked ~ label:before {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
.ui.radio.checkbox input:focus:checked ~ label:after {
|
||||
background-color: rgba(0, 0, 0, 0.95);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Slider
|
||||
---------------*/
|
||||
|
||||
.ui.slider.checkbox {
|
||||
min-height: 1.25rem;
|
||||
}
|
||||
|
||||
/* Input */
|
||||
.ui.slider.checkbox input {
|
||||
width: 3.5rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
/* Label */
|
||||
.ui.slider.checkbox label {
|
||||
padding-left: 4.5rem;
|
||||
line-height: 1rem;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
/* Line */
|
||||
.ui.slider.checkbox label:before {
|
||||
display: block;
|
||||
position: absolute;
|
||||
content: '';
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
border: none !important;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
top: 0.4rem;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
width: 3.5rem;
|
||||
height: 0.21428571rem;
|
||||
border-radius: 500rem;
|
||||
-webkit-transition: background 0.3s ease;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
.ui.slider.checkbox label:after {
|
||||
background: #FFFFFF -webkit-gradient(linear, left top, left bottom, from(transparent), to(rgba(0, 0, 0, 0.05)));
|
||||
background: #FFFFFF -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
|
||||
background: #FFFFFF linear-gradient(transparent, rgba(0, 0, 0, 0.05));
|
||||
position: absolute;
|
||||
content: '' !important;
|
||||
opacity: 1;
|
||||
z-index: 2;
|
||||
border: none;
|
||||
-webkit-box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
top: -0.25rem;
|
||||
left: 0;
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
border-radius: 500rem;
|
||||
-webkit-transition: left 0.3s ease;
|
||||
transition: left 0.3s ease;
|
||||
}
|
||||
|
||||
/* Focus */
|
||||
.ui.slider.checkbox input:focus ~ label:before {
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
.ui.slider.checkbox label:hover {
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
.ui.slider.checkbox label:hover::before {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Active */
|
||||
.ui.slider.checkbox input:checked ~ label {
|
||||
color: rgba(0, 0, 0, 0.95) !important;
|
||||
}
|
||||
.ui.slider.checkbox input:checked ~ label:before {
|
||||
background-color: #545454 !important;
|
||||
}
|
||||
.ui.slider.checkbox input:checked ~ label:after {
|
||||
left: 2rem;
|
||||
}
|
||||
|
||||
/* Active Focus */
|
||||
.ui.slider.checkbox input:focus:checked ~ label {
|
||||
color: rgba(0, 0, 0, 0.95) !important;
|
||||
}
|
||||
.ui.slider.checkbox input:focus:checked ~ label:before {
|
||||
background-color: #000000 !important;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Toggle
|
||||
---------------*/
|
||||
|
||||
.ui.toggle.checkbox {
|
||||
min-height: 1.5rem;
|
||||
}
|
||||
|
||||
/* Input */
|
||||
.ui.toggle.checkbox input {
|
||||
width: 3.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
/* Label */
|
||||
.ui.toggle.checkbox label {
|
||||
min-height: 1.5rem;
|
||||
padding-left: 4.5rem;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.ui.toggle.checkbox label {
|
||||
padding-top: 0.15em;
|
||||
}
|
||||
|
||||
/* Switch */
|
||||
.ui.toggle.checkbox label:before {
|
||||
display: block;
|
||||
position: absolute;
|
||||
content: '';
|
||||
z-index: 1;
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
border: none;
|
||||
top: 0;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
width: 3.5rem;
|
||||
height: 1.5rem;
|
||||
border-radius: 500rem;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
.ui.toggle.checkbox label:after {
|
||||
background: #FFFFFF -webkit-gradient(linear, left top, left bottom, from(transparent), to(rgba(0, 0, 0, 0.05)));
|
||||
background: #FFFFFF -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
|
||||
background: #FFFFFF linear-gradient(transparent, rgba(0, 0, 0, 0.05));
|
||||
position: absolute;
|
||||
content: '' !important;
|
||||
opacity: 1;
|
||||
z-index: 2;
|
||||
border: none;
|
||||
-webkit-box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-radius: 500rem;
|
||||
-webkit-transition: background 0.3s ease, left 0.3s ease;
|
||||
transition: background 0.3s ease, left 0.3s ease;
|
||||
}
|
||||
.ui.toggle.checkbox input ~ label:after {
|
||||
left: -0.05rem;
|
||||
-webkit-box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
||||
}
|
||||
|
||||
/* Focus */
|
||||
.ui.toggle.checkbox input:focus ~ label:before {
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
.ui.toggle.checkbox label:hover::before {
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Active */
|
||||
.ui.toggle.checkbox input:checked ~ label {
|
||||
color: rgba(0, 0, 0, 0.95) !important;
|
||||
}
|
||||
.ui.toggle.checkbox input:checked ~ label:before {
|
||||
background-color: #2185D0 !important;
|
||||
}
|
||||
.ui.toggle.checkbox input:checked ~ label:after {
|
||||
left: 2.15rem;
|
||||
-webkit-box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
||||
box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
|
||||
}
|
||||
|
||||
/* Active Focus */
|
||||
.ui.toggle.checkbox input:focus:checked ~ label {
|
||||
color: rgba(0, 0, 0, 0.95) !important;
|
||||
}
|
||||
.ui.toggle.checkbox input:focus:checked ~ label:before {
|
||||
background-color: #0d71bb !important;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Variations
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Fitted
|
||||
---------------*/
|
||||
|
||||
.ui.fitted.checkbox label {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
.ui.fitted.toggle.checkbox {
|
||||
width: 3.5rem;
|
||||
}
|
||||
.ui.fitted.slider.checkbox {
|
||||
width: 3.5rem;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Inverted
|
||||
---------------*/
|
||||
|
||||
.ui.inverted.checkbox label,
|
||||
.ui.inverted.checkbox + label {
|
||||
color: rgba(255, 255, 255, 0.9) !important;
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
.ui.inverted.checkbox label:hover {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
.ui.inverted.checkbox label:hover::before {
|
||||
border-color: rgba(34, 36, 38, 0.5);
|
||||
}
|
||||
/*Slider Label */
|
||||
.ui.inverted.slider.checkbox label {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
/* Slider Line */
|
||||
.ui.inverted.slider.checkbox label:before {
|
||||
background-color: rgba(255, 255, 255, 0.5) !important;
|
||||
}
|
||||
|
||||
/* Slider Hover */
|
||||
.ui.inverted.slider.checkbox label:hover::before {
|
||||
background: rgba(255, 255, 255, 0.7) !important;
|
||||
}
|
||||
|
||||
/* Slider Active */
|
||||
.ui.inverted.slider.checkbox input:checked ~ label {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
.ui.inverted.slider.checkbox input:checked ~ label:before {
|
||||
background-color: rgba(255, 255, 255, 0.8) !important;
|
||||
}
|
||||
|
||||
/* Slider Active Focus */
|
||||
.ui.inverted.slider.checkbox input:focus:checked ~ label {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
.ui.inverted.slider.checkbox input:focus:checked ~ label:before {
|
||||
background-color: rgba(255, 255, 255, 0.8) !important;
|
||||
}
|
||||
|
||||
/* Toggle Switch */
|
||||
.ui.inverted.toggle.checkbox label:before {
|
||||
background-color: rgba(255, 255, 255, 0.9) !important;
|
||||
}
|
||||
|
||||
/* Toggle Hover */
|
||||
.ui.inverted.toggle.checkbox label:hover::before {
|
||||
background: #ffffff !important;
|
||||
}
|
||||
|
||||
/* Toggle Active */
|
||||
.ui.inverted.toggle.checkbox input:checked ~ label {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
.ui.inverted.toggle.checkbox input:checked ~ label:before {
|
||||
background-color: #2185D0 !important;
|
||||
}
|
||||
|
||||
/* Toggle Active Focus */
|
||||
.ui.inverted.toggle.checkbox input:focus:checked ~ label {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
.ui.inverted.toggle.checkbox input:focus:checked ~ label:before {
|
||||
background-color: #0d71bb !important;
|
||||
}
|
||||
|
||||
/*--------------------
|
||||
Size
|
||||
---------------------*/
|
||||
|
||||
.ui.mini.checkbox {
|
||||
font-size: 0.78571429em;
|
||||
}
|
||||
.ui.tiny.checkbox {
|
||||
font-size: 0.85714286em;
|
||||
}
|
||||
.ui.small.checkbox {
|
||||
font-size: 0.92857143em;
|
||||
}
|
||||
.ui.large.checkbox {
|
||||
font-size: 1.14285714em;
|
||||
}
|
||||
.ui.large.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
||||
.ui.large.checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
||||
.ui.large.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before,
|
||||
.ui.large.checkbox:not(.slider):not(.toggle):not(.radio) label:before {
|
||||
-webkit-transform: scale(1.14285714);
|
||||
transform: scale(1.14285714);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
.ui.large.form .checkbox.radio label:before,
|
||||
.ui.large.checkbox.radio label:before {
|
||||
-webkit-transform: scale(1.14285714);
|
||||
transform: scale(1.14285714);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
.ui.large.form .checkbox.radio label:after,
|
||||
.ui.large.checkbox.radio label:after {
|
||||
-webkit-transform: scale(0.57142857);
|
||||
transform: scale(0.57142857);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
left: 0.33571429em;
|
||||
}
|
||||
.ui.big.checkbox {
|
||||
font-size: 1.28571429em;
|
||||
}
|
||||
.ui.big.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
||||
.ui.big.checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
||||
.ui.big.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before,
|
||||
.ui.big.checkbox:not(.slider):not(.toggle):not(.radio) label:before {
|
||||
-webkit-transform: scale(1.28571429);
|
||||
transform: scale(1.28571429);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
.ui.big.form .checkbox.radio label:before,
|
||||
.ui.big.checkbox.radio label:before {
|
||||
-webkit-transform: scale(1.28571429);
|
||||
transform: scale(1.28571429);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
.ui.big.form .checkbox.radio label:after,
|
||||
.ui.big.checkbox.radio label:after {
|
||||
-webkit-transform: scale(0.64285714);
|
||||
transform: scale(0.64285714);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
left: 0.37142857em;
|
||||
}
|
||||
.ui.huge.checkbox {
|
||||
font-size: 1.42857143em;
|
||||
}
|
||||
.ui.huge.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
||||
.ui.huge.checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
||||
.ui.huge.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before,
|
||||
.ui.huge.checkbox:not(.slider):not(.toggle):not(.radio) label:before {
|
||||
-webkit-transform: scale(1.42857143);
|
||||
transform: scale(1.42857143);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
.ui.huge.form .checkbox.radio label:before,
|
||||
.ui.huge.checkbox.radio label:before {
|
||||
-webkit-transform: scale(1.42857143);
|
||||
transform: scale(1.42857143);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
.ui.huge.form .checkbox.radio label:after,
|
||||
.ui.huge.checkbox.radio label:after {
|
||||
-webkit-transform: scale(0.71428571);
|
||||
transform: scale(0.71428571);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
left: 0.40714286em;
|
||||
}
|
||||
.ui.massive.checkbox {
|
||||
font-size: 1.71428571em;
|
||||
}
|
||||
.ui.massive.form .checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
||||
.ui.massive.checkbox:not(.slider):not(.toggle):not(.radio) label:after,
|
||||
.ui.massive.form .checkbox:not(.slider):not(.toggle):not(.radio) label:before,
|
||||
.ui.massive.checkbox:not(.slider):not(.toggle):not(.radio) label:before {
|
||||
-webkit-transform: scale(1.71428571);
|
||||
transform: scale(1.71428571);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
.ui.massive.form .checkbox.radio label:before,
|
||||
.ui.massive.checkbox.radio label:before {
|
||||
-webkit-transform: scale(1.71428571);
|
||||
transform: scale(1.71428571);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
}
|
||||
.ui.massive.form .checkbox.radio label:after,
|
||||
.ui.massive.checkbox.radio label:after {
|
||||
-webkit-transform: scale(0.85714286);
|
||||
transform: scale(0.85714286);
|
||||
-webkit-transform-origin: left;
|
||||
transform-origin: left;
|
||||
left: 0.47857143em;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Checkbox';
|
||||
src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBD8AAAC8AAAAYGNtYXAYVtCJAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5Zn4huwUAAAF4AAABYGhlYWQGPe1ZAAAC2AAAADZoaGVhB30DyAAAAxAAAAAkaG10eBBKAEUAAAM0AAAAHGxvY2EAmgESAAADUAAAABBtYXhwAAkALwAAA2AAAAAgbmFtZSC8IugAAAOAAAABknBvc3QAAwAAAAAFFAAAACAAAwMTAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADoAgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6AL//f//AAAAAAAg6AD//f//AAH/4xgEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAEUAUQO7AvgAGgAAARQHAQYjIicBJjU0PwE2MzIfAQE2MzIfARYVA7sQ/hQQFhcQ/uMQEE4QFxcQqAF2EBcXEE4QAnMWEP4UEBABHRAXFhBOEBCoAXcQEE4QFwAAAAABAAABbgMlAkkAFAAAARUUBwYjISInJj0BNDc2MyEyFxYVAyUQEBf9SRcQEBAQFwK3FxAQAhJtFxAQEBAXbRcQEBAQFwAAAAABAAAASQMlA24ALAAAARUUBwYrARUUBwYrASInJj0BIyInJj0BNDc2OwE1NDc2OwEyFxYdATMyFxYVAyUQEBfuEBAXbhYQEO4XEBAQEBfuEBAWbhcQEO4XEBACEm0XEBDuFxAQEBAX7hAQF20XEBDuFxAQEBAX7hAQFwAAAQAAAAIAAHRSzT9fDzz1AAsEAAAAAADRsdR3AAAAANGx1HcAAAAAA7sDbgAAAAgAAgAAAAAAAAABAAADwP/AAAAEAAAAAAADuwABAAAAAAAAAAAAAAAAAAAABwQAAAAAAAAAAAAAAAIAAAAEAABFAyUAAAMlAAAAAAAAAAoAFAAeAE4AcgCwAAEAAAAHAC0AAQAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAIAAAAAQAAAAAAAgAHAGkAAQAAAAAAAwAIADkAAQAAAAAABAAIAH4AAQAAAAAABQALABgAAQAAAAAABgAIAFEAAQAAAAAACgAaAJYAAwABBAkAAQAQAAgAAwABBAkAAgAOAHAAAwABBAkAAwAQAEEAAwABBAkABAAQAIYAAwABBAkABQAWACMAAwABBAkABgAQAFkAAwABBAkACgA0ALBDaGVja2JveABDAGgAZQBjAGsAYgBvAHhWZXJzaW9uIDIuMABWAGUAcgBzAGkAbwBuACAAMgAuADBDaGVja2JveABDAGgAZQBjAGsAYgBvAHhDaGVja2JveABDAGgAZQBjAGsAYgBvAHhSZWd1bGFyAFIAZQBnAHUAbABhAHJDaGVja2JveABDAGgAZQBjAGsAYgBvAHhGb250IGdlbmVyYXRlZCBieSBJY29Nb29uLgBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype');
|
||||
}
|
||||
|
||||
/* Checkmark */
|
||||
.ui.checkbox label:after,
|
||||
.ui.checkbox .box:after {
|
||||
font-family: 'Checkbox';
|
||||
}
|
||||
|
||||
/* Checked */
|
||||
.ui.checkbox input:checked ~ .box:after,
|
||||
.ui.checkbox input:checked ~ label:after {
|
||||
content: '\e800';
|
||||
}
|
||||
|
||||
/* Indeterminate */
|
||||
.ui.checkbox input:indeterminate ~ .box:after,
|
||||
.ui.checkbox input:indeterminate ~ label:after {
|
||||
font-size: 12px;
|
||||
content: '\e801';
|
||||
}
|
||||
/* UTF Reference
|
||||
.check:before { content: '\e800'; }
|
||||
.dash:before { content: '\e801'; }
|
||||
.plus:before { content: '\e802'; }
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Site Overrides
|
||||
*******************************/
|
||||
|
||||
876
src-angular/assets/semantic/dist/components/checkbox.js
vendored
Normal file
@@ -0,0 +1,876 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Checkbox
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
;(function ($, window, document, undefined) {
|
||||
|
||||
'use strict';
|
||||
|
||||
$.isFunction = $.isFunction || function(obj) {
|
||||
return typeof obj === "function" && typeof obj.nodeType !== "number";
|
||||
};
|
||||
|
||||
window = (typeof window != 'undefined' && window.Math == Math)
|
||||
? window
|
||||
: (typeof self != 'undefined' && self.Math == Math)
|
||||
? self
|
||||
: Function('return this')()
|
||||
;
|
||||
|
||||
$.fn.checkbox = function(parameters) {
|
||||
var
|
||||
$allModules = $(this),
|
||||
moduleSelector = $allModules.selector || '',
|
||||
|
||||
time = new Date().getTime(),
|
||||
performance = [],
|
||||
|
||||
query = arguments[0],
|
||||
methodInvoked = (typeof query == 'string'),
|
||||
queryArguments = [].slice.call(arguments, 1),
|
||||
returnedValue
|
||||
;
|
||||
|
||||
$allModules
|
||||
.each(function() {
|
||||
var
|
||||
settings = $.extend(true, {}, $.fn.checkbox.settings, parameters),
|
||||
|
||||
className = settings.className,
|
||||
namespace = settings.namespace,
|
||||
selector = settings.selector,
|
||||
error = settings.error,
|
||||
|
||||
eventNamespace = '.' + namespace,
|
||||
moduleNamespace = 'module-' + namespace,
|
||||
|
||||
$module = $(this),
|
||||
$label = $(this).children(selector.label),
|
||||
$input = $(this).children(selector.input),
|
||||
input = $input[0],
|
||||
|
||||
initialLoad = false,
|
||||
shortcutPressed = false,
|
||||
instance = $module.data(moduleNamespace),
|
||||
|
||||
observer,
|
||||
element = this,
|
||||
module
|
||||
;
|
||||
|
||||
module = {
|
||||
|
||||
initialize: function() {
|
||||
module.verbose('Initializing checkbox', settings);
|
||||
|
||||
module.create.label();
|
||||
module.bind.events();
|
||||
|
||||
module.set.tabbable();
|
||||
module.hide.input();
|
||||
|
||||
module.observeChanges();
|
||||
module.instantiate();
|
||||
module.setup();
|
||||
},
|
||||
|
||||
instantiate: function() {
|
||||
module.verbose('Storing instance of module', module);
|
||||
instance = module;
|
||||
$module
|
||||
.data(moduleNamespace, module)
|
||||
;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
module.verbose('Destroying module');
|
||||
module.unbind.events();
|
||||
module.show.input();
|
||||
$module.removeData(moduleNamespace);
|
||||
},
|
||||
|
||||
fix: {
|
||||
reference: function() {
|
||||
if( $module.is(selector.input) ) {
|
||||
module.debug('Behavior called on <input> adjusting invoked element');
|
||||
$module = $module.closest(selector.checkbox);
|
||||
module.refresh();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setup: function() {
|
||||
module.set.initialLoad();
|
||||
if( module.is.indeterminate() ) {
|
||||
module.debug('Initial value is indeterminate');
|
||||
module.indeterminate();
|
||||
}
|
||||
else if( module.is.checked() ) {
|
||||
module.debug('Initial value is checked');
|
||||
module.check();
|
||||
}
|
||||
else {
|
||||
module.debug('Initial value is unchecked');
|
||||
module.uncheck();
|
||||
}
|
||||
module.remove.initialLoad();
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
$label = $module.children(selector.label);
|
||||
$input = $module.children(selector.input);
|
||||
input = $input[0];
|
||||
},
|
||||
|
||||
hide: {
|
||||
input: function() {
|
||||
module.verbose('Modifying <input> z-index to be unselectable');
|
||||
$input.addClass(className.hidden);
|
||||
}
|
||||
},
|
||||
show: {
|
||||
input: function() {
|
||||
module.verbose('Modifying <input> z-index to be selectable');
|
||||
$input.removeClass(className.hidden);
|
||||
}
|
||||
},
|
||||
|
||||
observeChanges: function() {
|
||||
if('MutationObserver' in window) {
|
||||
observer = new MutationObserver(function(mutations) {
|
||||
module.debug('DOM tree modified, updating selector cache');
|
||||
module.refresh();
|
||||
});
|
||||
observer.observe(element, {
|
||||
childList : true,
|
||||
subtree : true
|
||||
});
|
||||
module.debug('Setting up mutation observer', observer);
|
||||
}
|
||||
},
|
||||
|
||||
attachEvents: function(selector, event) {
|
||||
var
|
||||
$element = $(selector)
|
||||
;
|
||||
event = $.isFunction(module[event])
|
||||
? module[event]
|
||||
: module.toggle
|
||||
;
|
||||
if($element.length > 0) {
|
||||
module.debug('Attaching checkbox events to element', selector, event);
|
||||
$element
|
||||
.on('click' + eventNamespace, event)
|
||||
;
|
||||
}
|
||||
else {
|
||||
module.error(error.notFound);
|
||||
}
|
||||
},
|
||||
|
||||
preventDefaultOnInputTarget: function() {
|
||||
if(typeof event !== 'undefined' && event !== null && $(event.target).is(selector.input)) {
|
||||
module.verbose('Preventing default check action after manual check action');
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
event: {
|
||||
change: function(event) {
|
||||
if( !module.should.ignoreCallbacks() ) {
|
||||
settings.onChange.call(input);
|
||||
}
|
||||
},
|
||||
click: function(event) {
|
||||
var
|
||||
$target = $(event.target)
|
||||
;
|
||||
if( $target.is(selector.input) ) {
|
||||
module.verbose('Using default check action on initialized checkbox');
|
||||
return;
|
||||
}
|
||||
if( $target.is(selector.link) ) {
|
||||
module.debug('Clicking link inside checkbox, skipping toggle');
|
||||
return;
|
||||
}
|
||||
module.toggle();
|
||||
$input.focus();
|
||||
event.preventDefault();
|
||||
},
|
||||
keydown: function(event) {
|
||||
var
|
||||
key = event.which,
|
||||
keyCode = {
|
||||
enter : 13,
|
||||
space : 32,
|
||||
escape : 27,
|
||||
left : 37,
|
||||
up : 38,
|
||||
right : 39,
|
||||
down : 40
|
||||
}
|
||||
;
|
||||
|
||||
var r = module.get.radios(),
|
||||
rIndex = r.index($module),
|
||||
rLen = r.length,
|
||||
checkIndex = false;
|
||||
|
||||
if(key == keyCode.left || key == keyCode.up) {
|
||||
checkIndex = (rIndex === 0 ? rLen : rIndex) - 1;
|
||||
} else if(key == keyCode.right || key == keyCode.down) {
|
||||
checkIndex = rIndex === rLen-1 ? 0 : rIndex+1;
|
||||
}
|
||||
|
||||
if (!module.should.ignoreCallbacks() && checkIndex !== false) {
|
||||
if(settings.beforeUnchecked.apply(input)===false) {
|
||||
module.verbose('Option not allowed to be unchecked, cancelling key navigation');
|
||||
return false;
|
||||
}
|
||||
if (settings.beforeChecked.apply($(r[checkIndex]).children(selector.input)[0])===false) {
|
||||
module.verbose('Next option should not allow check, cancelling key navigation');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(key == keyCode.escape) {
|
||||
module.verbose('Escape key pressed blurring field');
|
||||
$input.blur();
|
||||
shortcutPressed = true;
|
||||
}
|
||||
else if(!event.ctrlKey && ( key == keyCode.space || (key == keyCode.enter && settings.enableEnterKey)) ) {
|
||||
module.verbose('Enter/space key pressed, toggling checkbox');
|
||||
module.toggle();
|
||||
shortcutPressed = true;
|
||||
}
|
||||
else {
|
||||
shortcutPressed = false;
|
||||
}
|
||||
},
|
||||
keyup: function(event) {
|
||||
if(shortcutPressed) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
check: function() {
|
||||
if( !module.should.allowCheck() ) {
|
||||
return;
|
||||
}
|
||||
module.debug('Checking checkbox', $input);
|
||||
module.set.checked();
|
||||
if( !module.should.ignoreCallbacks() ) {
|
||||
settings.onChecked.call(input);
|
||||
module.trigger.change();
|
||||
}
|
||||
module.preventDefaultOnInputTarget();
|
||||
},
|
||||
|
||||
uncheck: function() {
|
||||
if( !module.should.allowUncheck() ) {
|
||||
return;
|
||||
}
|
||||
module.debug('Unchecking checkbox');
|
||||
module.set.unchecked();
|
||||
if( !module.should.ignoreCallbacks() ) {
|
||||
settings.onUnchecked.call(input);
|
||||
module.trigger.change();
|
||||
}
|
||||
module.preventDefaultOnInputTarget();
|
||||
},
|
||||
|
||||
indeterminate: function() {
|
||||
if( module.should.allowIndeterminate() ) {
|
||||
module.debug('Checkbox is already indeterminate');
|
||||
return;
|
||||
}
|
||||
module.debug('Making checkbox indeterminate');
|
||||
module.set.indeterminate();
|
||||
if( !module.should.ignoreCallbacks() ) {
|
||||
settings.onIndeterminate.call(input);
|
||||
module.trigger.change();
|
||||
}
|
||||
},
|
||||
|
||||
determinate: function() {
|
||||
if( module.should.allowDeterminate() ) {
|
||||
module.debug('Checkbox is already determinate');
|
||||
return;
|
||||
}
|
||||
module.debug('Making checkbox determinate');
|
||||
module.set.determinate();
|
||||
if( !module.should.ignoreCallbacks() ) {
|
||||
settings.onDeterminate.call(input);
|
||||
module.trigger.change();
|
||||
}
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
if( module.is.enabled() ) {
|
||||
module.debug('Checkbox is already enabled');
|
||||
return;
|
||||
}
|
||||
module.debug('Enabling checkbox');
|
||||
module.set.enabled();
|
||||
if( !module.should.ignoreCallbacks() ) {
|
||||
settings.onEnable.call(input);
|
||||
// preserve legacy callbacks
|
||||
settings.onEnabled.call(input);
|
||||
module.trigger.change();
|
||||
}
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
if( module.is.disabled() ) {
|
||||
module.debug('Checkbox is already disabled');
|
||||
return;
|
||||
}
|
||||
module.debug('Disabling checkbox');
|
||||
module.set.disabled();
|
||||
if( !module.should.ignoreCallbacks() ) {
|
||||
settings.onDisable.call(input);
|
||||
// preserve legacy callbacks
|
||||
settings.onDisabled.call(input);
|
||||
module.trigger.change();
|
||||
}
|
||||
},
|
||||
|
||||
get: {
|
||||
radios: function() {
|
||||
var
|
||||
name = module.get.name()
|
||||
;
|
||||
return $('input[name="' + name + '"]').closest(selector.checkbox);
|
||||
},
|
||||
otherRadios: function() {
|
||||
return module.get.radios().not($module);
|
||||
},
|
||||
name: function() {
|
||||
return $input.attr('name');
|
||||
}
|
||||
},
|
||||
|
||||
is: {
|
||||
initialLoad: function() {
|
||||
return initialLoad;
|
||||
},
|
||||
radio: function() {
|
||||
return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
|
||||
},
|
||||
indeterminate: function() {
|
||||
return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
|
||||
},
|
||||
checked: function() {
|
||||
return $input.prop('checked') !== undefined && $input.prop('checked');
|
||||
},
|
||||
disabled: function() {
|
||||
return $input.prop('disabled') !== undefined && $input.prop('disabled');
|
||||
},
|
||||
enabled: function() {
|
||||
return !module.is.disabled();
|
||||
},
|
||||
determinate: function() {
|
||||
return !module.is.indeterminate();
|
||||
},
|
||||
unchecked: function() {
|
||||
return !module.is.checked();
|
||||
}
|
||||
},
|
||||
|
||||
should: {
|
||||
allowCheck: function() {
|
||||
if(module.is.determinate() && module.is.checked() && !module.is.initialLoad() ) {
|
||||
module.debug('Should not allow check, checkbox is already checked');
|
||||
return false;
|
||||
}
|
||||
if(!module.should.ignoreCallbacks() && settings.beforeChecked.apply(input) === false) {
|
||||
module.debug('Should not allow check, beforeChecked cancelled');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
allowUncheck: function() {
|
||||
if(module.is.determinate() && module.is.unchecked() && !module.is.initialLoad() ) {
|
||||
module.debug('Should not allow uncheck, checkbox is already unchecked');
|
||||
return false;
|
||||
}
|
||||
if(!module.should.ignoreCallbacks() && settings.beforeUnchecked.apply(input) === false) {
|
||||
module.debug('Should not allow uncheck, beforeUnchecked cancelled');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
allowIndeterminate: function() {
|
||||
if(module.is.indeterminate() && !module.is.initialLoad() ) {
|
||||
module.debug('Should not allow indeterminate, checkbox is already indeterminate');
|
||||
return false;
|
||||
}
|
||||
if(!module.should.ignoreCallbacks() && settings.beforeIndeterminate.apply(input) === false) {
|
||||
module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
allowDeterminate: function() {
|
||||
if(module.is.determinate() && !module.is.initialLoad() ) {
|
||||
module.debug('Should not allow determinate, checkbox is already determinate');
|
||||
return false;
|
||||
}
|
||||
if(!module.should.ignoreCallbacks() && settings.beforeDeterminate.apply(input) === false) {
|
||||
module.debug('Should not allow determinate, beforeDeterminate cancelled');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
ignoreCallbacks: function() {
|
||||
return (initialLoad && !settings.fireOnInit);
|
||||
}
|
||||
},
|
||||
|
||||
can: {
|
||||
change: function() {
|
||||
return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
|
||||
},
|
||||
uncheck: function() {
|
||||
return (typeof settings.uncheckable === 'boolean')
|
||||
? settings.uncheckable
|
||||
: !module.is.radio()
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
set: {
|
||||
initialLoad: function() {
|
||||
initialLoad = true;
|
||||
},
|
||||
checked: function() {
|
||||
module.verbose('Setting class to checked');
|
||||
$module
|
||||
.removeClass(className.indeterminate)
|
||||
.addClass(className.checked)
|
||||
;
|
||||
if( module.is.radio() ) {
|
||||
module.uncheckOthers();
|
||||
}
|
||||
if(!module.is.indeterminate() && module.is.checked()) {
|
||||
module.debug('Input is already checked, skipping input property change');
|
||||
return;
|
||||
}
|
||||
module.verbose('Setting state to checked', input);
|
||||
$input
|
||||
.prop('indeterminate', false)
|
||||
.prop('checked', true)
|
||||
;
|
||||
},
|
||||
unchecked: function() {
|
||||
module.verbose('Removing checked class');
|
||||
$module
|
||||
.removeClass(className.indeterminate)
|
||||
.removeClass(className.checked)
|
||||
;
|
||||
if(!module.is.indeterminate() && module.is.unchecked() ) {
|
||||
module.debug('Input is already unchecked');
|
||||
return;
|
||||
}
|
||||
module.debug('Setting state to unchecked');
|
||||
$input
|
||||
.prop('indeterminate', false)
|
||||
.prop('checked', false)
|
||||
;
|
||||
},
|
||||
indeterminate: function() {
|
||||
module.verbose('Setting class to indeterminate');
|
||||
$module
|
||||
.addClass(className.indeterminate)
|
||||
;
|
||||
if( module.is.indeterminate() ) {
|
||||
module.debug('Input is already indeterminate, skipping input property change');
|
||||
return;
|
||||
}
|
||||
module.debug('Setting state to indeterminate');
|
||||
$input
|
||||
.prop('indeterminate', true)
|
||||
;
|
||||
},
|
||||
determinate: function() {
|
||||
module.verbose('Removing indeterminate class');
|
||||
$module
|
||||
.removeClass(className.indeterminate)
|
||||
;
|
||||
if( module.is.determinate() ) {
|
||||
module.debug('Input is already determinate, skipping input property change');
|
||||
return;
|
||||
}
|
||||
module.debug('Setting state to determinate');
|
||||
$input
|
||||
.prop('indeterminate', false)
|
||||
;
|
||||
},
|
||||
disabled: function() {
|
||||
module.verbose('Setting class to disabled');
|
||||
$module
|
||||
.addClass(className.disabled)
|
||||
;
|
||||
if( module.is.disabled() ) {
|
||||
module.debug('Input is already disabled, skipping input property change');
|
||||
return;
|
||||
}
|
||||
module.debug('Setting state to disabled');
|
||||
$input
|
||||
.prop('disabled', 'disabled')
|
||||
;
|
||||
},
|
||||
enabled: function() {
|
||||
module.verbose('Removing disabled class');
|
||||
$module.removeClass(className.disabled);
|
||||
if( module.is.enabled() ) {
|
||||
module.debug('Input is already enabled, skipping input property change');
|
||||
return;
|
||||
}
|
||||
module.debug('Setting state to enabled');
|
||||
$input
|
||||
.prop('disabled', false)
|
||||
;
|
||||
},
|
||||
tabbable: function() {
|
||||
module.verbose('Adding tabindex to checkbox');
|
||||
if( $input.attr('tabindex') === undefined) {
|
||||
$input.attr('tabindex', 0);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
remove: {
|
||||
initialLoad: function() {
|
||||
initialLoad = false;
|
||||
}
|
||||
},
|
||||
|
||||
trigger: {
|
||||
change: function() {
|
||||
var
|
||||
events = document.createEvent('HTMLEvents'),
|
||||
inputElement = $input[0]
|
||||
;
|
||||
if(inputElement) {
|
||||
module.verbose('Triggering native change event');
|
||||
events.initEvent('change', true, false);
|
||||
inputElement.dispatchEvent(events);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
create: {
|
||||
label: function() {
|
||||
if($input.prevAll(selector.label).length > 0) {
|
||||
$input.prev(selector.label).detach().insertAfter($input);
|
||||
module.debug('Moving existing label', $label);
|
||||
}
|
||||
else if( !module.has.label() ) {
|
||||
$label = $('<label>').insertAfter($input);
|
||||
module.debug('Creating label', $label);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
has: {
|
||||
label: function() {
|
||||
return ($label.length > 0);
|
||||
}
|
||||
},
|
||||
|
||||
bind: {
|
||||
events: function() {
|
||||
module.verbose('Attaching checkbox events');
|
||||
$module
|
||||
.on('click' + eventNamespace, module.event.click)
|
||||
.on('change' + eventNamespace, module.event.change)
|
||||
.on('keydown' + eventNamespace, selector.input, module.event.keydown)
|
||||
.on('keyup' + eventNamespace, selector.input, module.event.keyup)
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
unbind: {
|
||||
events: function() {
|
||||
module.debug('Removing events');
|
||||
$module
|
||||
.off(eventNamespace)
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
uncheckOthers: function() {
|
||||
var
|
||||
$radios = module.get.otherRadios()
|
||||
;
|
||||
module.debug('Unchecking other radios', $radios);
|
||||
$radios.removeClass(className.checked);
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
if( !module.can.change() ) {
|
||||
if(!module.is.radio()) {
|
||||
module.debug('Checkbox is read-only or disabled, ignoring toggle');
|
||||
}
|
||||
return;
|
||||
}
|
||||
if( module.is.indeterminate() || module.is.unchecked() ) {
|
||||
module.debug('Currently unchecked');
|
||||
module.check();
|
||||
}
|
||||
else if( module.is.checked() && module.can.uncheck() ) {
|
||||
module.debug('Currently checked');
|
||||
module.uncheck();
|
||||
}
|
||||
},
|
||||
setting: function(name, value) {
|
||||
module.debug('Changing setting', name, value);
|
||||
if( $.isPlainObject(name) ) {
|
||||
$.extend(true, settings, name);
|
||||
}
|
||||
else if(value !== undefined) {
|
||||
if($.isPlainObject(settings[name])) {
|
||||
$.extend(true, settings[name], value);
|
||||
}
|
||||
else {
|
||||
settings[name] = value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return settings[name];
|
||||
}
|
||||
},
|
||||
internal: function(name, value) {
|
||||
if( $.isPlainObject(name) ) {
|
||||
$.extend(true, module, name);
|
||||
}
|
||||
else if(value !== undefined) {
|
||||
module[name] = value;
|
||||
}
|
||||
else {
|
||||
return module[name];
|
||||
}
|
||||
},
|
||||
debug: function() {
|
||||
if(!settings.silent && settings.debug) {
|
||||
if(settings.performance) {
|
||||
module.performance.log(arguments);
|
||||
}
|
||||
else {
|
||||
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
||||
module.debug.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
},
|
||||
verbose: function() {
|
||||
if(!settings.silent && settings.verbose && settings.debug) {
|
||||
if(settings.performance) {
|
||||
module.performance.log(arguments);
|
||||
}
|
||||
else {
|
||||
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
||||
module.verbose.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
if(!settings.silent) {
|
||||
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
|
||||
module.error.apply(console, arguments);
|
||||
}
|
||||
},
|
||||
performance: {
|
||||
log: function(message) {
|
||||
var
|
||||
currentTime,
|
||||
executionTime,
|
||||
previousTime
|
||||
;
|
||||
if(settings.performance) {
|
||||
currentTime = new Date().getTime();
|
||||
previousTime = time || currentTime;
|
||||
executionTime = currentTime - previousTime;
|
||||
time = currentTime;
|
||||
performance.push({
|
||||
'Name' : message[0],
|
||||
'Arguments' : [].slice.call(message, 1) || '',
|
||||
'Element' : element,
|
||||
'Execution Time' : executionTime
|
||||
});
|
||||
}
|
||||
clearTimeout(module.performance.timer);
|
||||
module.performance.timer = setTimeout(module.performance.display, 500);
|
||||
},
|
||||
display: function() {
|
||||
var
|
||||
title = settings.name + ':',
|
||||
totalTime = 0
|
||||
;
|
||||
time = false;
|
||||
clearTimeout(module.performance.timer);
|
||||
$.each(performance, function(index, data) {
|
||||
totalTime += data['Execution Time'];
|
||||
});
|
||||
title += ' ' + totalTime + 'ms';
|
||||
if(moduleSelector) {
|
||||
title += ' \'' + moduleSelector + '\'';
|
||||
}
|
||||
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
|
||||
console.groupCollapsed(title);
|
||||
if(console.table) {
|
||||
console.table(performance);
|
||||
}
|
||||
else {
|
||||
$.each(performance, function(index, data) {
|
||||
console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
|
||||
});
|
||||
}
|
||||
console.groupEnd();
|
||||
}
|
||||
performance = [];
|
||||
}
|
||||
},
|
||||
invoke: function(query, passedArguments, context) {
|
||||
var
|
||||
object = instance,
|
||||
maxDepth,
|
||||
found,
|
||||
response
|
||||
;
|
||||
passedArguments = passedArguments || queryArguments;
|
||||
context = element || context;
|
||||
if(typeof query == 'string' && object !== undefined) {
|
||||
query = query.split(/[\. ]/);
|
||||
maxDepth = query.length - 1;
|
||||
$.each(query, function(depth, value) {
|
||||
var camelCaseValue = (depth != maxDepth)
|
||||
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
|
||||
: query
|
||||
;
|
||||
if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
|
||||
object = object[camelCaseValue];
|
||||
}
|
||||
else if( object[camelCaseValue] !== undefined ) {
|
||||
found = object[camelCaseValue];
|
||||
return false;
|
||||
}
|
||||
else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
|
||||
object = object[value];
|
||||
}
|
||||
else if( object[value] !== undefined ) {
|
||||
found = object[value];
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
module.error(error.method, query);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
if ( $.isFunction( found ) ) {
|
||||
response = found.apply(context, passedArguments);
|
||||
}
|
||||
else if(found !== undefined) {
|
||||
response = found;
|
||||
}
|
||||
if(Array.isArray(returnedValue)) {
|
||||
returnedValue.push(response);
|
||||
}
|
||||
else if(returnedValue !== undefined) {
|
||||
returnedValue = [returnedValue, response];
|
||||
}
|
||||
else if(response !== undefined) {
|
||||
returnedValue = response;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
if(methodInvoked) {
|
||||
if(instance === undefined) {
|
||||
module.initialize();
|
||||
}
|
||||
module.invoke(query);
|
||||
}
|
||||
else {
|
||||
if(instance !== undefined) {
|
||||
instance.invoke('destroy');
|
||||
}
|
||||
module.initialize();
|
||||
}
|
||||
})
|
||||
;
|
||||
|
||||
return (returnedValue !== undefined)
|
||||
? returnedValue
|
||||
: this
|
||||
;
|
||||
};
|
||||
|
||||
$.fn.checkbox.settings = {
|
||||
|
||||
name : 'Checkbox',
|
||||
namespace : 'checkbox',
|
||||
|
||||
silent : false,
|
||||
debug : false,
|
||||
verbose : true,
|
||||
performance : true,
|
||||
|
||||
// delegated event context
|
||||
uncheckable : 'auto',
|
||||
fireOnInit : false,
|
||||
enableEnterKey : true,
|
||||
|
||||
onChange : function(){},
|
||||
|
||||
beforeChecked : function(){},
|
||||
beforeUnchecked : function(){},
|
||||
beforeDeterminate : function(){},
|
||||
beforeIndeterminate : function(){},
|
||||
|
||||
onChecked : function(){},
|
||||
onUnchecked : function(){},
|
||||
|
||||
onDeterminate : function() {},
|
||||
onIndeterminate : function() {},
|
||||
|
||||
onEnable : function(){},
|
||||
onDisable : function(){},
|
||||
|
||||
// preserve misspelled callbacks (will be removed in 3.0)
|
||||
onEnabled : function(){},
|
||||
onDisabled : function(){},
|
||||
|
||||
className : {
|
||||
checked : 'checked',
|
||||
indeterminate : 'indeterminate',
|
||||
disabled : 'disabled',
|
||||
hidden : 'hidden',
|
||||
radio : 'radio',
|
||||
readOnly : 'read-only'
|
||||
},
|
||||
|
||||
error : {
|
||||
method : 'The method you called is not defined'
|
||||
},
|
||||
|
||||
selector : {
|
||||
checkbox : '.ui.checkbox',
|
||||
label : 'label, .box',
|
||||
input : 'input[type="checkbox"], input[type="radio"]',
|
||||
link : 'a[href]'
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
})( jQuery, window, document );
|
||||
9
src-angular/assets/semantic/dist/components/checkbox.min.css
vendored
Normal file
11
src-angular/assets/semantic/dist/components/checkbox.min.js
vendored
Normal file
296
src-angular/assets/semantic/dist/components/comment.css
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Comment
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Standard
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Comments
|
||||
---------------*/
|
||||
|
||||
.ui.comments {
|
||||
margin: 1.5em 0;
|
||||
max-width: 650px;
|
||||
}
|
||||
.ui.comments:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui.comments:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Comment
|
||||
---------------*/
|
||||
|
||||
.ui.comments .comment {
|
||||
position: relative;
|
||||
background: none;
|
||||
margin: 0.5em 0 0;
|
||||
padding: 0.5em 0 0;
|
||||
border: none;
|
||||
border-top: none;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.ui.comments .comment:first-child {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
/*--------------------
|
||||
Nested Comments
|
||||
---------------------*/
|
||||
|
||||
.ui.comments .comment > .comments {
|
||||
margin: 0 0 0.5em 0.5em;
|
||||
padding: 1em 0 1em 1em;
|
||||
}
|
||||
.ui.comments .comment > .comments:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.ui.comments .comment > .comments .comment {
|
||||
border: none;
|
||||
border-top: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Avatar
|
||||
---------------*/
|
||||
|
||||
.ui.comments .comment .avatar {
|
||||
display: block;
|
||||
width: 2.5em;
|
||||
height: auto;
|
||||
float: left;
|
||||
margin: 0.2em 0 0;
|
||||
}
|
||||
.ui.comments .comment img.avatar,
|
||||
.ui.comments .comment .avatar img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Content
|
||||
---------------*/
|
||||
|
||||
.ui.comments .comment > .content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* If there is an avatar move content over */
|
||||
.ui.comments .comment > .avatar ~ .content {
|
||||
margin-left: 3.5em;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Author
|
||||
---------------*/
|
||||
|
||||
.ui.comments .comment .author {
|
||||
font-size: 1em;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
font-weight: bold;
|
||||
}
|
||||
.ui.comments .comment a.author {
|
||||
cursor: pointer;
|
||||
}
|
||||
.ui.comments .comment a.author:hover {
|
||||
color: #1e70bf;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Metadata
|
||||
---------------*/
|
||||
|
||||
.ui.comments .comment .metadata {
|
||||
display: inline-block;
|
||||
margin-left: 0.5em;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
font-size: 0.875em;
|
||||
}
|
||||
.ui.comments .comment .metadata > * {
|
||||
display: inline-block;
|
||||
margin: 0 0.5em 0 0;
|
||||
}
|
||||
.ui.comments .comment .metadata > :last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/*--------------------
|
||||
Comment Text
|
||||
---------------------*/
|
||||
|
||||
.ui.comments .comment .text {
|
||||
margin: 0.25em 0 0.5em;
|
||||
font-size: 1em;
|
||||
word-wrap: break-word;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/*--------------------
|
||||
User Actions
|
||||
---------------------*/
|
||||
|
||||
.ui.comments .comment .actions {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
.ui.comments .comment .actions a {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 0 0.75em 0 0;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.ui.comments .comment .actions a:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
.ui.comments .comment .actions a.active,
|
||||
.ui.comments .comment .actions a:hover {
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
/*--------------------
|
||||
Reply Form
|
||||
---------------------*/
|
||||
|
||||
.ui.comments > .reply.form {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.ui.comments .comment .reply.form {
|
||||
width: 100%;
|
||||
margin-top: 1em;
|
||||
}
|
||||
.ui.comments .reply.form textarea {
|
||||
font-size: 1em;
|
||||
height: 12em;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
State
|
||||
*******************************/
|
||||
|
||||
.ui.collapsed.comments,
|
||||
.ui.comments .collapsed.comments,
|
||||
.ui.comments .collapsed.comment {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Variations
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------------
|
||||
Threaded
|
||||
---------------------*/
|
||||
|
||||
.ui.threaded.comments .comment > .comments {
|
||||
margin: -1.5em 0 -1em 1.25em;
|
||||
padding: 3em 0 2em 2.25em;
|
||||
-webkit-box-shadow: -1px 0 0 rgba(34, 36, 38, 0.15);
|
||||
box-shadow: -1px 0 0 rgba(34, 36, 38, 0.15);
|
||||
}
|
||||
|
||||
/*--------------------
|
||||
Minimal
|
||||
---------------------*/
|
||||
|
||||
.ui.minimal.comments .comment .actions {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: auto;
|
||||
-webkit-transition: opacity 0.2s ease;
|
||||
transition: opacity 0.2s ease;
|
||||
-webkit-transition-delay: 0.1s;
|
||||
transition-delay: 0.1s;
|
||||
}
|
||||
.ui.minimal.comments .comment > .content:hover > .actions {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/*-------------------
|
||||
Sizes
|
||||
--------------------*/
|
||||
|
||||
.ui.comments {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.ui.mini.comments {
|
||||
font-size: 0.78571429rem;
|
||||
}
|
||||
.ui.tiny.comments {
|
||||
font-size: 0.85714286rem;
|
||||
}
|
||||
.ui.small.comments {
|
||||
font-size: 0.92857143rem;
|
||||
}
|
||||
.ui.large.comments {
|
||||
font-size: 1.14285714rem;
|
||||
}
|
||||
.ui.big.comments {
|
||||
font-size: 1.28571429rem;
|
||||
}
|
||||
.ui.huge.comments {
|
||||
font-size: 1.42857143rem;
|
||||
}
|
||||
.ui.massive.comments {
|
||||
font-size: 1.71428571rem;
|
||||
}
|
||||
|
||||
/*-------------------
|
||||
Inverted
|
||||
--------------------*/
|
||||
|
||||
.ui.inverted.comments .comment {
|
||||
background-color: #1B1C1D;
|
||||
}
|
||||
.ui.inverted.comments .comment .author,
|
||||
.ui.inverted.comments .comment .text {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
.ui.inverted.comments .comment .metadata,
|
||||
.ui.inverted.comments .comment .actions a {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
.ui.inverted.comments .comment a.author:hover,
|
||||
.ui.inverted.comments .comment .actions a.active,
|
||||
.ui.inverted.comments .comment .actions a:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
.ui.inverted.threaded.comments .comment > .comments {
|
||||
-webkit-box-shadow: -1px 0 0 #555555;
|
||||
box-shadow: -1px 0 0 #555555;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
User Variable Overrides
|
||||
*******************************/
|
||||
|
||||
9
src-angular/assets/semantic/dist/components/comment.min.css
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Comment
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/.ui.comments{margin:1.5em 0;max-width:650px}.ui.comments:first-child{margin-top:0}.ui.comments:last-child{margin-bottom:0}.ui.comments .comment{position:relative;background:0 0;margin:.5em 0 0;padding:.5em 0 0;border:none;border-top:none;line-height:1.2}.ui.comments .comment:first-child{margin-top:0;padding-top:0}.ui.comments .comment>.comments{margin:0 0 .5em .5em;padding:1em 0 1em 1em}.ui.comments .comment>.comments:before{position:absolute;top:0;left:0}.ui.comments .comment>.comments .comment{border:none;border-top:none;background:0 0}.ui.comments .comment .avatar{display:block;width:2.5em;height:auto;float:left;margin:.2em 0 0}.ui.comments .comment .avatar img,.ui.comments .comment img.avatar{display:block;margin:0 auto;width:100%;height:100%;border-radius:.25rem}.ui.comments .comment>.content{display:block}.ui.comments .comment>.avatar~.content{margin-left:3.5em}.ui.comments .comment .author{font-size:1em;color:rgba(0,0,0,.87);font-weight:700}.ui.comments .comment a.author{cursor:pointer}.ui.comments .comment a.author:hover{color:#1e70bf}.ui.comments .comment .metadata{display:inline-block;margin-left:.5em;color:rgba(0,0,0,.4);font-size:.875em}.ui.comments .comment .metadata>*{display:inline-block;margin:0 .5em 0 0}.ui.comments .comment .metadata>:last-child{margin-right:0}.ui.comments .comment .text{margin:.25em 0 .5em;font-size:1em;word-wrap:break-word;color:rgba(0,0,0,.87);line-height:1.3}.ui.comments .comment .actions{font-size:.875em}.ui.comments .comment .actions a{cursor:pointer;display:inline-block;margin:0 .75em 0 0;color:rgba(0,0,0,.4)}.ui.comments .comment .actions a:last-child{margin-right:0}.ui.comments .comment .actions a.active,.ui.comments .comment .actions a:hover{color:rgba(0,0,0,.8)}.ui.comments>.reply.form{margin-top:1em}.ui.comments .comment .reply.form{width:100%;margin-top:1em}.ui.comments .reply.form textarea{font-size:1em;height:12em}.ui.collapsed.comments,.ui.comments .collapsed.comment,.ui.comments .collapsed.comments{display:none}.ui.threaded.comments .comment>.comments{margin:-1.5em 0 -1em 1.25em;padding:3em 0 2em 2.25em;-webkit-box-shadow:-1px 0 0 rgba(34,36,38,.15);box-shadow:-1px 0 0 rgba(34,36,38,.15)}.ui.minimal.comments .comment .actions{opacity:0;position:absolute;top:0;right:0;left:auto;-webkit-transition:opacity .2s ease;transition:opacity .2s ease;-webkit-transition-delay:.1s;transition-delay:.1s}.ui.minimal.comments .comment>.content:hover>.actions{opacity:1}.ui.comments{font-size:1rem}.ui.mini.comments{font-size:.78571429rem}.ui.tiny.comments{font-size:.85714286rem}.ui.small.comments{font-size:.92857143rem}.ui.large.comments{font-size:1.14285714rem}.ui.big.comments{font-size:1.28571429rem}.ui.huge.comments{font-size:1.42857143rem}.ui.massive.comments{font-size:1.71428571rem}.ui.inverted.comments .comment{background-color:#1b1c1d}.ui.inverted.comments .comment .author,.ui.inverted.comments .comment .text{color:rgba(255,255,255,.9)}.ui.inverted.comments .comment .actions a,.ui.inverted.comments .comment .metadata{color:rgba(255,255,255,.7)}.ui.inverted.comments .comment .actions a.active,.ui.inverted.comments .comment .actions a:hover,.ui.inverted.comments .comment a.author:hover{color:#fff}.ui.inverted.threaded.comments .comment>.comments{-webkit-box-shadow:-1px 0 0 #555;box-shadow:-1px 0 0 #555}
|
||||
145
src-angular/assets/semantic/dist/components/container.css
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Container
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Container
|
||||
*******************************/
|
||||
|
||||
|
||||
/* All Sizes */
|
||||
.ui.container {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
@media only screen and (max-width: 767.98px) {
|
||||
.ui.ui.ui.container:not(.fluid) {
|
||||
width: auto;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
.ui.ui.ui.grid.container {
|
||||
width: auto;
|
||||
}
|
||||
.ui.ui.ui.relaxed.grid.container {
|
||||
width: auto;
|
||||
}
|
||||
.ui.ui.ui.very.relaxed.grid.container {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablet */
|
||||
@media only screen and (min-width: 768px) and (max-width: 991.98px) {
|
||||
.ui.ui.ui.container:not(.fluid) {
|
||||
width: 723px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.ui.ui.ui.grid.container {
|
||||
width: calc(723px + 2rem);
|
||||
}
|
||||
.ui.ui.ui.relaxed.grid.container {
|
||||
width: calc(723px + 3rem);
|
||||
}
|
||||
.ui.ui.ui.very.relaxed.grid.container {
|
||||
width: calc(723px + 5rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* Small Monitor */
|
||||
@media only screen and (min-width: 992px) and (max-width: 1199.98px) {
|
||||
.ui.ui.ui.container:not(.fluid) {
|
||||
width: 933px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.ui.ui.ui.grid.container {
|
||||
width: calc(933px + 2rem);
|
||||
}
|
||||
.ui.ui.ui.relaxed.grid.container {
|
||||
width: calc(933px + 3rem);
|
||||
}
|
||||
.ui.ui.ui.very.relaxed.grid.container {
|
||||
width: calc(933px + 5rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* Large Monitor */
|
||||
@media only screen and (min-width: 1200px) {
|
||||
.ui.ui.ui.container:not(.fluid) {
|
||||
width: 1127px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.ui.ui.ui.grid.container {
|
||||
width: calc(1127px + 2rem);
|
||||
}
|
||||
.ui.ui.ui.relaxed.grid.container {
|
||||
width: calc(1127px + 3rem);
|
||||
}
|
||||
.ui.ui.ui.very.relaxed.grid.container {
|
||||
width: calc(1127px + 5rem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Types
|
||||
*******************************/
|
||||
|
||||
|
||||
/* Text Container */
|
||||
.ui.text.container {
|
||||
font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;
|
||||
max-width: 700px;
|
||||
line-height: 1.5;
|
||||
font-size: 1.14285714rem;
|
||||
}
|
||||
|
||||
/* Fluid */
|
||||
.ui.fluid.container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Variations
|
||||
*******************************/
|
||||
|
||||
.ui[class*="left aligned"].container {
|
||||
text-align: left;
|
||||
}
|
||||
.ui[class*="center aligned"].container {
|
||||
text-align: center;
|
||||
}
|
||||
.ui[class*="right aligned"].container {
|
||||
text-align: right;
|
||||
}
|
||||
.ui.justified.container {
|
||||
text-align: justify;
|
||||
-webkit-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
Site Overrides
|
||||
*******************************/
|
||||
|
||||
9
src-angular/assets/semantic/dist/components/container.min.css
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Container
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/.ui.container{display:block;max-width:100%}@media only screen and (max-width:767.98px){.ui.ui.ui.container:not(.fluid){width:auto;margin-left:1em;margin-right:1em}.ui.ui.ui.grid.container{width:auto}.ui.ui.ui.relaxed.grid.container{width:auto}.ui.ui.ui.very.relaxed.grid.container{width:auto}}@media only screen and (min-width:768px) and (max-width:991.98px){.ui.ui.ui.container:not(.fluid){width:723px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(723px + 2rem)}.ui.ui.ui.relaxed.grid.container{width:calc(723px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(723px + 5rem)}}@media only screen and (min-width:992px) and (max-width:1199.98px){.ui.ui.ui.container:not(.fluid){width:933px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(933px + 2rem)}.ui.ui.ui.relaxed.grid.container{width:calc(933px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(933px + 5rem)}}@media only screen and (min-width:1200px){.ui.ui.ui.container:not(.fluid){width:1127px;margin-left:auto;margin-right:auto}.ui.ui.ui.grid.container{width:calc(1127px + 2rem)}.ui.ui.ui.relaxed.grid.container{width:calc(1127px + 3rem)}.ui.ui.ui.very.relaxed.grid.container{width:calc(1127px + 5rem)}}.ui.text.container{font-family:Lato,'Helvetica Neue',Arial,Helvetica,sans-serif;max-width:700px;line-height:1.5;font-size:1.14285714rem}.ui.fluid.container{width:100%}.ui[class*="left aligned"].container{text-align:left}.ui[class*="center aligned"].container{text-align:center}.ui[class*="right aligned"].container{text-align:right}.ui.justified.container{text-align:justify;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}
|
||||
464
src-angular/assets/semantic/dist/components/dimmer.css
vendored
Normal file
@@ -0,0 +1,464 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Dimmer
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Dimmer
|
||||
*******************************/
|
||||
|
||||
.dimmable:not(body) {
|
||||
position: relative;
|
||||
}
|
||||
.ui.dimmer {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
padding: 1em;
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
opacity: 0;
|
||||
line-height: 1;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
-webkit-animation-duration: 0.5s;
|
||||
animation-duration: 0.5s;
|
||||
-webkit-transition: background-color 0.5s linear;
|
||||
transition: background-color 0.5s linear;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
will-change: opacity;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
/* Dimmer Content */
|
||||
.ui.dimmer > .content {
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
-ms-user-select: text;
|
||||
user-select: text;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* Loose Coupling */
|
||||
.ui.segment > .ui.dimmer:not(.page) {
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
/* Scrollbars */
|
||||
.ui.dimmer:not(.inverted)::-webkit-scrollbar-track {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
.ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb:window-inactive {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
.ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
States
|
||||
*******************************/
|
||||
|
||||
|
||||
/* Animating */
|
||||
.animating.dimmable:not(body),
|
||||
.dimmed.dimmable:not(body) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Animating / Active / Visible */
|
||||
.dimmed.dimmable > .ui.animating.dimmer,
|
||||
.dimmed.dimmable > .ui.visible.dimmer,
|
||||
.ui.active.dimmer {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
.ui.disabled.dimmer {
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Variations
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Legacy
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Animating / Active / Visible */
|
||||
.dimmed.dimmable > .ui.animating.legacy.dimmer,
|
||||
.dimmed.dimmable > .ui.visible.legacy.dimmer,
|
||||
.ui.active.legacy.dimmer {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Alignment
|
||||
---------------*/
|
||||
|
||||
.ui[class*="top aligned"].dimmer {
|
||||
-webkit-box-pack: start;
|
||||
-ms-flex-pack: start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.ui[class*="bottom aligned"].dimmer {
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Page
|
||||
---------------*/
|
||||
|
||||
.ui.page.dimmer {
|
||||
position: fixed;
|
||||
-webkit-transform-style: '';
|
||||
transform-style: '';
|
||||
-webkit-perspective: 2000px;
|
||||
perspective: 2000px;
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center;
|
||||
}
|
||||
body.animating.in.dimmable,
|
||||
body.dimmed.dimmable {
|
||||
overflow: hidden;
|
||||
}
|
||||
body.dimmable > .dimmer {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Blurring
|
||||
---------------*/
|
||||
|
||||
.blurring.dimmable > :not(.dimmer) {
|
||||
-webkit-filter: initial;
|
||||
filter: initial;
|
||||
-webkit-transition: 800ms -webkit-filter ease;
|
||||
transition: 800ms -webkit-filter ease;
|
||||
transition: 800ms filter ease;
|
||||
transition: 800ms filter ease, 800ms -webkit-filter ease;
|
||||
}
|
||||
.blurring.dimmed.dimmable > :not(.dimmer):not(.popup) {
|
||||
-webkit-filter: blur(5px) grayscale(0.7);
|
||||
filter: blur(5px) grayscale(0.7);
|
||||
}
|
||||
|
||||
/* Dimmer Color */
|
||||
.blurring.dimmable > .dimmer {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.blurring.dimmable > .inverted.dimmer {
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Aligned
|
||||
---------------*/
|
||||
|
||||
.ui.dimmer > .top.aligned.content > * {
|
||||
vertical-align: top;
|
||||
}
|
||||
.ui.dimmer > .bottom.aligned.content > * {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Shades
|
||||
---------------*/
|
||||
|
||||
.medium.medium.medium.medium.medium.dimmer {
|
||||
background-color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
.light.light.light.light.light.dimmer {
|
||||
background-color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
.very.light.light.light.light.dimmer {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Inverted
|
||||
---------------*/
|
||||
|
||||
.ui.inverted.dimmer {
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
.ui.inverted.dimmer > .content,
|
||||
.ui.inverted.dimmer > .content > * {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Inverted Shades
|
||||
---------------*/
|
||||
|
||||
.medium.medium.medium.medium.medium.inverted.dimmer {
|
||||
background-color: rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
.light.light.light.light.light.inverted.dimmer {
|
||||
background-color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
.very.light.light.light.light.inverted.dimmer {
|
||||
background-color: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Simple
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Displays without javascript */
|
||||
.ui.simple.dimmer {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
z-index: -100;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
.dimmed.dimmable > .ui.simple.dimmer {
|
||||
overflow: visible;
|
||||
opacity: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
z-index: 1;
|
||||
}
|
||||
.ui.simple.inverted.dimmer {
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
}
|
||||
.dimmed.dimmable > .ui.simple.inverted.dimmer {
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Partially
|
||||
----------------*/
|
||||
|
||||
.ui[class*="top dimmer"],
|
||||
.ui[class*="center dimmer"],
|
||||
.ui[class*="bottom dimmer"] {
|
||||
height: auto;
|
||||
}
|
||||
.ui[class*="bottom dimmer"] {
|
||||
top: auto !important;
|
||||
bottom: 0;
|
||||
}
|
||||
.ui[class*="center dimmer"] {
|
||||
top: 50% !important;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
.ui.segment > .ui.ui[class*="top dimmer"] {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.ui.segment > .ui.ui[class*="center dimmer"] {
|
||||
border-radius: 0;
|
||||
}
|
||||
.ui.segment > .ui.ui[class*="bottom dimmer"] {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
.ui[class*="center dimmer"].transition[class*="fade up"].in {
|
||||
-webkit-animation-name: fadeInUpCenter;
|
||||
animation-name: fadeInUpCenter;
|
||||
}
|
||||
.ui[class*="center dimmer"].transition[class*="fade down"].in {
|
||||
-webkit-animation-name: fadeInDownCenter;
|
||||
animation-name: fadeInDownCenter;
|
||||
}
|
||||
.ui[class*="center dimmer"].transition[class*="fade up"].out {
|
||||
-webkit-animation-name: fadeOutUpCenter;
|
||||
animation-name: fadeOutUpCenter;
|
||||
}
|
||||
.ui[class*="center dimmer"].transition[class*="fade down"].out {
|
||||
-webkit-animation-name: fadeOutDownCenter;
|
||||
animation-name: fadeOutDownCenter;
|
||||
}
|
||||
.ui[class*="center dimmer"].bounce.transition {
|
||||
-webkit-animation-name: bounceCenter;
|
||||
animation-name: bounceCenter;
|
||||
}
|
||||
@-webkit-keyframes fadeInUpCenter {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-40%);
|
||||
-webkit-transform: translateY(calc(-40% - 0.5px));
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
}
|
||||
@keyframes fadeInUpCenter {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-40%);
|
||||
-webkit-transform: translateY(calc(-40% - 0.5px));
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fadeInDownCenter {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-60%);
|
||||
-webkit-transform: translateY(calc(-60% - 0.5px));
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
}
|
||||
@keyframes fadeInDownCenter {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-60%);
|
||||
-webkit-transform: translateY(calc(-60% - 0.5px));
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fadeOutUpCenter {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-45%);
|
||||
-webkit-transform: translateY(calc(-45% - 0.5px));
|
||||
}
|
||||
}
|
||||
@keyframes fadeOutUpCenter {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-45%);
|
||||
-webkit-transform: translateY(calc(-45% - 0.5px));
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fadeOutDownCenter {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-55%);
|
||||
-webkit-transform: translateY(calc(-55% - 0.5px));
|
||||
}
|
||||
}
|
||||
@keyframes fadeOutDownCenter {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-55%);
|
||||
-webkit-transform: translateY(calc(-55% - 0.5px));
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes bounceCenter {
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: translateY(calc(-50% - 30px));
|
||||
transform: translateY(calc(-50% - 30px));
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: translateY(calc(-50% - 15px));
|
||||
transform: translateY(calc(-50% - 15px));
|
||||
}
|
||||
}
|
||||
@keyframes bounceCenter {
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: translateY(-50%);
|
||||
-webkit-transform: translateY(calc(-50% - 0.5px));
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: translateY(calc(-50% - 30px));
|
||||
transform: translateY(calc(-50% - 30px));
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: translateY(calc(-50% - 15px));
|
||||
transform: translateY(calc(-50% - 15px));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
User Overrides
|
||||
*******************************/
|
||||
|
||||
753
src-angular/assets/semantic/dist/components/dimmer.js
vendored
Normal file
@@ -0,0 +1,753 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Dimmer
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
;(function ($, window, document, undefined) {
|
||||
|
||||
'use strict';
|
||||
|
||||
$.isFunction = $.isFunction || function(obj) {
|
||||
return typeof obj === "function" && typeof obj.nodeType !== "number";
|
||||
};
|
||||
|
||||
window = (typeof window != 'undefined' && window.Math == Math)
|
||||
? window
|
||||
: (typeof self != 'undefined' && self.Math == Math)
|
||||
? self
|
||||
: Function('return this')()
|
||||
;
|
||||
|
||||
$.fn.dimmer = function(parameters) {
|
||||
var
|
||||
$allModules = $(this),
|
||||
|
||||
time = new Date().getTime(),
|
||||
performance = [],
|
||||
|
||||
query = arguments[0],
|
||||
methodInvoked = (typeof query == 'string'),
|
||||
queryArguments = [].slice.call(arguments, 1),
|
||||
|
||||
returnedValue
|
||||
;
|
||||
|
||||
$allModules
|
||||
.each(function() {
|
||||
var
|
||||
settings = ( $.isPlainObject(parameters) )
|
||||
? $.extend(true, {}, $.fn.dimmer.settings, parameters)
|
||||
: $.extend({}, $.fn.dimmer.settings),
|
||||
|
||||
selector = settings.selector,
|
||||
namespace = settings.namespace,
|
||||
className = settings.className,
|
||||
error = settings.error,
|
||||
|
||||
eventNamespace = '.' + namespace,
|
||||
moduleNamespace = 'module-' + namespace,
|
||||
moduleSelector = $allModules.selector || '',
|
||||
|
||||
clickEvent = ('ontouchstart' in document.documentElement)
|
||||
? 'touchstart'
|
||||
: 'click',
|
||||
|
||||
$module = $(this),
|
||||
$dimmer,
|
||||
$dimmable,
|
||||
|
||||
element = this,
|
||||
instance = $module.data(moduleNamespace),
|
||||
module
|
||||
;
|
||||
|
||||
module = {
|
||||
|
||||
preinitialize: function() {
|
||||
if( module.is.dimmer() ) {
|
||||
|
||||
$dimmable = $module.parent();
|
||||
$dimmer = $module;
|
||||
}
|
||||
else {
|
||||
$dimmable = $module;
|
||||
if( module.has.dimmer() ) {
|
||||
if(settings.dimmerName) {
|
||||
$dimmer = $dimmable.find(selector.dimmer).filter('.' + settings.dimmerName);
|
||||
}
|
||||
else {
|
||||
$dimmer = $dimmable.find(selector.dimmer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$dimmer = module.create();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
module.debug('Initializing dimmer', settings);
|
||||
|
||||
module.bind.events();
|
||||
module.set.dimmable();
|
||||
module.instantiate();
|
||||
},
|
||||
|
||||
instantiate: function() {
|
||||
module.verbose('Storing instance of module', module);
|
||||
instance = module;
|
||||
$module
|
||||
.data(moduleNamespace, instance)
|
||||
;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
module.verbose('Destroying previous module', $dimmer);
|
||||
module.unbind.events();
|
||||
module.remove.variation();
|
||||
$dimmable
|
||||
.off(eventNamespace)
|
||||
;
|
||||
},
|
||||
|
||||
bind: {
|
||||
events: function() {
|
||||
if(settings.on == 'hover') {
|
||||
$dimmable
|
||||
.on('mouseenter' + eventNamespace, module.show)
|
||||
.on('mouseleave' + eventNamespace, module.hide)
|
||||
;
|
||||
}
|
||||
else if(settings.on == 'click') {
|
||||
$dimmable
|
||||
.on(clickEvent + eventNamespace, module.toggle)
|
||||
;
|
||||
}
|
||||
if( module.is.page() ) {
|
||||
module.debug('Setting as a page dimmer', $dimmable);
|
||||
module.set.pageDimmer();
|
||||
}
|
||||
|
||||
if( module.is.closable() ) {
|
||||
module.verbose('Adding dimmer close event', $dimmer);
|
||||
$dimmable
|
||||
.on(clickEvent + eventNamespace, selector.dimmer, module.event.click)
|
||||
;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
unbind: {
|
||||
events: function() {
|
||||
$module
|
||||
.removeData(moduleNamespace)
|
||||
;
|
||||
$dimmable
|
||||
.off(eventNamespace)
|
||||
;
|
||||
}
|
||||
},
|
||||
|
||||
event: {
|
||||
click: function(event) {
|
||||
module.verbose('Determining if event occured on dimmer', event);
|
||||
if( $dimmer.find(event.target).length === 0 || $(event.target).is(selector.content) ) {
|
||||
module.hide();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addContent: function(element) {
|
||||
var
|
||||
$content = $(element)
|
||||
;
|
||||
module.debug('Add content to dimmer', $content);
|
||||
if($content.parent()[0] !== $dimmer[0]) {
|
||||
$content.detach().appendTo($dimmer);
|
||||
}
|
||||
},
|
||||
|
||||
create: function() {
|
||||
var
|
||||
$element = $( settings.template.dimmer(settings) )
|
||||
;
|
||||
if(settings.dimmerName) {
|
||||
module.debug('Creating named dimmer', settings.dimmerName);
|
||||
$element.addClass(settings.dimmerName);
|
||||
}
|
||||
$element
|
||||
.appendTo($dimmable)
|
||||
;
|
||||
return $element;
|
||||
},
|
||||
|
||||
show: function(callback) {
|
||||
callback = $.isFunction(callback)
|
||||
? callback
|
||||
: function(){}
|
||||
;
|
||||
module.debug('Showing dimmer', $dimmer, settings);
|
||||
module.set.variation();
|
||||
if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
|
||||
module.animate.show(callback);
|
||||
settings.onShow.call(element);
|
||||
settings.onChange.call(element);
|
||||
}
|
||||
else {
|
||||
module.debug('Dimmer is already shown or disabled');
|
||||
}
|
||||
},
|
||||
|
||||
hide: function(callback) {
|
||||
callback = $.isFunction(callback)
|
||||
? callback
|
||||
: function(){}
|
||||
;
|
||||
if( module.is.dimmed() || module.is.animating() ) {
|
||||
module.debug('Hiding dimmer', $dimmer);
|
||||
module.animate.hide(callback);
|
||||
settings.onHide.call(element);
|
||||
settings.onChange.call(element);
|
||||
}
|
||||
else {
|
||||
module.debug('Dimmer is not visible');
|
||||
}
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
module.verbose('Toggling dimmer visibility', $dimmer);
|
||||
if( !module.is.dimmed() ) {
|
||||
module.show();
|
||||
}
|
||||
else {
|
||||
if ( module.is.closable() ) {
|
||||
module.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
animate: {
|
||||
show: function(callback) {
|
||||
callback = $.isFunction(callback)
|
||||
? callback
|
||||
: function(){}
|
||||
;
|
||||
if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
|
||||
if(settings.useFlex) {
|
||||
module.debug('Using flex dimmer');
|
||||
module.remove.legacy();
|
||||
}
|
||||
else {
|
||||
module.debug('Using legacy non-flex dimmer');
|
||||
module.set.legacy();
|
||||
}
|
||||
if(settings.opacity !== 'auto') {
|
||||
module.set.opacity();
|
||||
}
|
||||
$dimmer
|
||||
.transition({
|
||||
displayType : settings.useFlex
|
||||
? 'flex'
|
||||
: 'block',
|
||||
animation : settings.transition + ' in',
|
||||
queue : false,
|
||||
duration : module.get.duration(),
|
||||
useFailSafe : true,
|
||||
onStart : function() {
|
||||
module.set.dimmed();
|
||||
},
|
||||
onComplete : function() {
|
||||
module.set.active();
|
||||
callback();
|
||||
}
|
||||
})
|
||||
;
|
||||
}
|
||||
else {
|
||||
module.verbose('Showing dimmer animation with javascript');
|
||||
module.set.dimmed();
|
||||
if(settings.opacity == 'auto') {
|
||||
settings.opacity = 0.8;
|
||||
}
|
||||
$dimmer
|
||||
.stop()
|
||||
.css({
|
||||
opacity : 0,
|
||||
width : '100%',
|
||||
height : '100%'
|
||||
})
|
||||
.fadeTo(module.get.duration(), settings.opacity, function() {
|
||||
$dimmer.removeAttr('style');
|
||||
module.set.active();
|
||||
callback();
|
||||
})
|
||||
;
|
||||
}
|
||||
},
|
||||
hide: function(callback) {
|
||||
callback = $.isFunction(callback)
|
||||
? callback
|
||||
: function(){}
|
||||
;
|
||||
if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
|
||||
module.verbose('Hiding dimmer with css');
|
||||
$dimmer
|
||||
.transition({
|
||||
displayType : settings.useFlex
|
||||
? 'flex'
|
||||
: 'block',
|
||||
animation : settings.transition + ' out',
|
||||
queue : false,
|
||||
duration : module.get.duration(),
|
||||
useFailSafe : true,
|
||||
onComplete : function() {
|
||||
module.remove.dimmed();
|
||||
module.remove.variation();
|
||||
module.remove.active();
|
||||
callback();
|
||||
}
|
||||
})
|
||||
;
|
||||
}
|
||||
else {
|
||||
module.verbose('Hiding dimmer with javascript');
|
||||
$dimmer
|
||||
.stop()
|
||||
.fadeOut(module.get.duration(), function() {
|
||||
module.remove.dimmed();
|
||||
module.remove.active();
|
||||
$dimmer.removeAttr('style');
|
||||
callback();
|
||||
})
|
||||
;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get: {
|
||||
dimmer: function() {
|
||||
return $dimmer;
|
||||
},
|
||||
duration: function() {
|
||||
if(typeof settings.duration == 'object') {
|
||||
if( module.is.active() ) {
|
||||
return settings.duration.hide;
|
||||
}
|
||||
else {
|
||||
return settings.duration.show;
|
||||
}
|
||||
}
|
||||
return settings.duration;
|
||||
}
|
||||
},
|
||||
|
||||
has: {
|
||||
dimmer: function() {
|
||||
if(settings.dimmerName) {
|
||||
return ($module.find(selector.dimmer).filter('.' + settings.dimmerName).length > 0);
|
||||
}
|
||||
else {
|
||||
return ( $module.find(selector.dimmer).length > 0 );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
is: {
|
||||
active: function() {
|
||||
return $dimmer.hasClass(className.active);
|
||||
},
|
||||
animating: function() {
|
||||
return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
|
||||
},
|
||||
closable: function() {
|
||||
if(settings.closable == 'auto') {
|
||||
if(settings.on == 'hover') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return settings.closable;
|
||||
},
|
||||
dimmer: function() {
|
||||
return $module.hasClass(className.dimmer);
|
||||
},
|
||||
dimmable: function() {
|
||||
return $module.hasClass(className.dimmable);
|
||||
},
|
||||
dimmed: function() {
|
||||
return $dimmable.hasClass(className.dimmed);
|
||||
},
|
||||
disabled: function() {
|
||||
return $dimmable.hasClass(className.disabled);
|
||||
},
|
||||
enabled: function() {
|
||||
return !module.is.disabled();
|
||||
},
|
||||
page: function () {
|
||||
return $dimmable.is('body');
|
||||
},
|
||||
pageDimmer: function() {
|
||||
return $dimmer.hasClass(className.pageDimmer);
|
||||
}
|
||||
},
|
||||
|
||||
can: {
|
||||
show: function() {
|
||||
return !$dimmer.hasClass(className.disabled);
|
||||
}
|
||||
},
|
||||
|
||||
set: {
|
||||
opacity: function(opacity) {
|
||||
var
|
||||
color = $dimmer.css('background-color'),
|
||||
colorArray = color.split(','),
|
||||
isRGB = (colorArray && colorArray.length == 3),
|
||||
isRGBA = (colorArray && colorArray.length == 4)
|
||||
;
|
||||
opacity = settings.opacity === 0 ? 0 : settings.opacity || opacity;
|
||||
if(isRGB || isRGBA) {
|
||||
colorArray[3] = opacity + ')';
|
||||
color = colorArray.join(',');
|
||||
}
|
||||
else {
|
||||
color = 'rgba(0, 0, 0, ' + opacity + ')';
|
||||
}
|
||||
module.debug('Setting opacity to', opacity);
|
||||
$dimmer.css('background-color', color);
|
||||
},
|
||||
legacy: function() {
|
||||
$dimmer.addClass(className.legacy);
|
||||
},
|
||||
active: function() {
|
||||
$dimmer.addClass(className.active);
|
||||
},
|
||||
dimmable: function() {
|
||||
$dimmable.addClass(className.dimmable);
|
||||
},
|
||||
dimmed: function() {
|
||||
$dimmable.addClass(className.dimmed);
|
||||
},
|
||||
pageDimmer: function() {
|
||||
$dimmer.addClass(className.pageDimmer);
|
||||
},
|
||||
disabled: function() {
|
||||
$dimmer.addClass(className.disabled);
|
||||
},
|
||||
variation: function(variation) {
|
||||
variation = variation || settings.variation;
|
||||
if(variation) {
|
||||
$dimmer.addClass(variation);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
remove: {
|
||||
active: function() {
|
||||
$dimmer
|
||||
.removeClass(className.active)
|
||||
;
|
||||
},
|
||||
legacy: function() {
|
||||
$dimmer.removeClass(className.legacy);
|
||||
},
|
||||
dimmed: function() {
|
||||
$dimmable.removeClass(className.dimmed);
|
||||
},
|
||||
disabled: function() {
|
||||
$dimmer.removeClass(className.disabled);
|
||||
},
|
||||
variation: function(variation) {
|
||||
variation = variation || settings.variation;
|
||||
if(variation) {
|
||||
$dimmer.removeClass(variation);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setting: function(name, value) {
|
||||
module.debug('Changing setting', name, value);
|
||||
if( $.isPlainObject(name) ) {
|
||||
$.extend(true, settings, name);
|
||||
}
|
||||
else if(value !== undefined) {
|
||||
if($.isPlainObject(settings[name])) {
|
||||
$.extend(true, settings[name], value);
|
||||
}
|
||||
else {
|
||||
settings[name] = value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return settings[name];
|
||||
}
|
||||
},
|
||||
internal: function(name, value) {
|
||||
if( $.isPlainObject(name) ) {
|
||||
$.extend(true, module, name);
|
||||
}
|
||||
else if(value !== undefined) {
|
||||
module[name] = value;
|
||||
}
|
||||
else {
|
||||
return module[name];
|
||||
}
|
||||
},
|
||||
debug: function() {
|
||||
if(!settings.silent && settings.debug) {
|
||||
if(settings.performance) {
|
||||
module.performance.log(arguments);
|
||||
}
|
||||
else {
|
||||
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
||||
module.debug.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
},
|
||||
verbose: function() {
|
||||
if(!settings.silent && settings.verbose && settings.debug) {
|
||||
if(settings.performance) {
|
||||
module.performance.log(arguments);
|
||||
}
|
||||
else {
|
||||
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
||||
module.verbose.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
if(!settings.silent) {
|
||||
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
|
||||
module.error.apply(console, arguments);
|
||||
}
|
||||
},
|
||||
performance: {
|
||||
log: function(message) {
|
||||
var
|
||||
currentTime,
|
||||
executionTime,
|
||||
previousTime
|
||||
;
|
||||
if(settings.performance) {
|
||||
currentTime = new Date().getTime();
|
||||
previousTime = time || currentTime;
|
||||
executionTime = currentTime - previousTime;
|
||||
time = currentTime;
|
||||
performance.push({
|
||||
'Name' : message[0],
|
||||
'Arguments' : [].slice.call(message, 1) || '',
|
||||
'Element' : element,
|
||||
'Execution Time' : executionTime
|
||||
});
|
||||
}
|
||||
clearTimeout(module.performance.timer);
|
||||
module.performance.timer = setTimeout(module.performance.display, 500);
|
||||
},
|
||||
display: function() {
|
||||
var
|
||||
title = settings.name + ':',
|
||||
totalTime = 0
|
||||
;
|
||||
time = false;
|
||||
clearTimeout(module.performance.timer);
|
||||
$.each(performance, function(index, data) {
|
||||
totalTime += data['Execution Time'];
|
||||
});
|
||||
title += ' ' + totalTime + 'ms';
|
||||
if(moduleSelector) {
|
||||
title += ' \'' + moduleSelector + '\'';
|
||||
}
|
||||
if($allModules.length > 1) {
|
||||
title += ' ' + '(' + $allModules.length + ')';
|
||||
}
|
||||
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
|
||||
console.groupCollapsed(title);
|
||||
if(console.table) {
|
||||
console.table(performance);
|
||||
}
|
||||
else {
|
||||
$.each(performance, function(index, data) {
|
||||
console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
|
||||
});
|
||||
}
|
||||
console.groupEnd();
|
||||
}
|
||||
performance = [];
|
||||
}
|
||||
},
|
||||
invoke: function(query, passedArguments, context) {
|
||||
var
|
||||
object = instance,
|
||||
maxDepth,
|
||||
found,
|
||||
response
|
||||
;
|
||||
passedArguments = passedArguments || queryArguments;
|
||||
context = element || context;
|
||||
if(typeof query == 'string' && object !== undefined) {
|
||||
query = query.split(/[\. ]/);
|
||||
maxDepth = query.length - 1;
|
||||
$.each(query, function(depth, value) {
|
||||
var camelCaseValue = (depth != maxDepth)
|
||||
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
|
||||
: query
|
||||
;
|
||||
if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
|
||||
object = object[camelCaseValue];
|
||||
}
|
||||
else if( object[camelCaseValue] !== undefined ) {
|
||||
found = object[camelCaseValue];
|
||||
return false;
|
||||
}
|
||||
else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
|
||||
object = object[value];
|
||||
}
|
||||
else if( object[value] !== undefined ) {
|
||||
found = object[value];
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
module.error(error.method, query);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
if ( $.isFunction( found ) ) {
|
||||
response = found.apply(context, passedArguments);
|
||||
}
|
||||
else if(found !== undefined) {
|
||||
response = found;
|
||||
}
|
||||
if(Array.isArray(returnedValue)) {
|
||||
returnedValue.push(response);
|
||||
}
|
||||
else if(returnedValue !== undefined) {
|
||||
returnedValue = [returnedValue, response];
|
||||
}
|
||||
else if(response !== undefined) {
|
||||
returnedValue = response;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
module.preinitialize();
|
||||
|
||||
if(methodInvoked) {
|
||||
if(instance === undefined) {
|
||||
module.initialize();
|
||||
}
|
||||
module.invoke(query);
|
||||
}
|
||||
else {
|
||||
if(instance !== undefined) {
|
||||
instance.invoke('destroy');
|
||||
}
|
||||
module.initialize();
|
||||
}
|
||||
})
|
||||
;
|
||||
|
||||
return (returnedValue !== undefined)
|
||||
? returnedValue
|
||||
: this
|
||||
;
|
||||
};
|
||||
|
||||
$.fn.dimmer.settings = {
|
||||
|
||||
name : 'Dimmer',
|
||||
namespace : 'dimmer',
|
||||
|
||||
silent : false,
|
||||
debug : false,
|
||||
verbose : false,
|
||||
performance : true,
|
||||
|
||||
// whether should use flex layout
|
||||
useFlex : true,
|
||||
|
||||
// name to distinguish between multiple dimmers in context
|
||||
dimmerName : false,
|
||||
|
||||
// whether to add a variation type
|
||||
variation : false,
|
||||
|
||||
// whether to bind close events
|
||||
closable : 'auto',
|
||||
|
||||
// whether to use css animations
|
||||
useCSS : true,
|
||||
|
||||
// css animation to use
|
||||
transition : 'fade',
|
||||
|
||||
// event to bind to
|
||||
on : false,
|
||||
|
||||
// overriding opacity value
|
||||
opacity : 'auto',
|
||||
|
||||
// transition durations
|
||||
duration : {
|
||||
show : 500,
|
||||
hide : 500
|
||||
},
|
||||
// whether the dynamically created dimmer should have a loader
|
||||
displayLoader: false,
|
||||
loaderText : false,
|
||||
loaderVariation : '',
|
||||
|
||||
onChange : function(){},
|
||||
onShow : function(){},
|
||||
onHide : function(){},
|
||||
|
||||
error : {
|
||||
method : 'The method you called is not defined.'
|
||||
},
|
||||
|
||||
className : {
|
||||
active : 'active',
|
||||
animating : 'animating',
|
||||
dimmable : 'dimmable',
|
||||
dimmed : 'dimmed',
|
||||
dimmer : 'dimmer',
|
||||
disabled : 'disabled',
|
||||
hide : 'hide',
|
||||
legacy : 'legacy',
|
||||
pageDimmer : 'page',
|
||||
show : 'show',
|
||||
loader : 'ui loader'
|
||||
},
|
||||
|
||||
selector: {
|
||||
dimmer : '> .ui.dimmer',
|
||||
content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
|
||||
},
|
||||
|
||||
template: {
|
||||
dimmer: function(settings) {
|
||||
var d = $('<div/>').addClass('ui dimmer'),l;
|
||||
if(settings.displayLoader) {
|
||||
l = $('<div/>')
|
||||
.addClass(settings.className.loader)
|
||||
.addClass(settings.loaderVariation);
|
||||
if(!!settings.loaderText){
|
||||
l.text(settings.loaderText);
|
||||
l.addClass('text');
|
||||
}
|
||||
d.append(l);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
})( jQuery, window, document );
|
||||
9
src-angular/assets/semantic/dist/components/dimmer.min.css
vendored
Normal file
11
src-angular/assets/semantic/dist/components/dimmer.min.js
vendored
Normal file
297
src-angular/assets/semantic/dist/components/divider.css
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
/*!
|
||||
* # Fomantic-UI - Divider
|
||||
* http://github.com/fomantic/Fomantic-UI/
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*******************************
|
||||
Divider
|
||||
*******************************/
|
||||
|
||||
.ui.divider {
|
||||
margin: 1rem 0;
|
||||
line-height: 1;
|
||||
height: 0;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Basic
|
||||
---------------*/
|
||||
|
||||
.ui.divider:not(.vertical):not(.horizontal) {
|
||||
border-top: 1px solid rgba(34, 36, 38, 0.15);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Coupling
|
||||
---------------*/
|
||||
|
||||
|
||||
/* Allow divider between each column row */
|
||||
.ui.grid > .column + .divider,
|
||||
.ui.grid > .row > .column + .divider {
|
||||
left: auto;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Horizontal
|
||||
---------------*/
|
||||
|
||||
.ui.horizontal.divider {
|
||||
display: table;
|
||||
white-space: nowrap;
|
||||
height: auto;
|
||||
margin: '';
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
}
|
||||
.ui.horizontal.divider:before,
|
||||
.ui.horizontal.divider:after {
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 50%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.ui.horizontal.divider:before {
|
||||
background-position: right 1em top 50%;
|
||||
}
|
||||
.ui.horizontal.divider:after {
|
||||
background-position: left 1em top 50%;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Vertical
|
||||
---------------*/
|
||||
|
||||
.ui.vertical.divider {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
height: 50%;
|
||||
line-height: 0;
|
||||
text-align: center;
|
||||
-webkit-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.ui.vertical.divider:before,
|
||||
.ui.vertical.divider:after {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
content: '';
|
||||
z-index: 3;
|
||||
border-left: 1px solid rgba(34, 36, 38, 0.15);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.1);
|
||||
width: 0;
|
||||
height: calc(100% - 1rem);
|
||||
}
|
||||
.ui.vertical.divider:before {
|
||||
top: -100%;
|
||||
}
|
||||
.ui.vertical.divider:after {
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
/* Inside grid */
|
||||
@media only screen and (max-width: 767.98px) {
|
||||
.ui.stackable.grid .ui.vertical.divider,
|
||||
.ui.grid .stackable.row .ui.vertical.divider {
|
||||
display: table;
|
||||
white-space: nowrap;
|
||||
height: auto;
|
||||
margin: '';
|
||||
overflow: hidden;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
position: static;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
}
|
||||
.ui.stackable.grid .ui.vertical.divider:before,
|
||||
.ui.grid .stackable.row .ui.vertical.divider:before,
|
||||
.ui.stackable.grid .ui.vertical.divider:after,
|
||||
.ui.grid .stackable.row .ui.vertical.divider:after {
|
||||
left: 0;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
content: '';
|
||||
display: table-cell;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
width: 50%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.ui.stackable.grid .ui.vertical.divider:before,
|
||||
.ui.grid .stackable.row .ui.vertical.divider:before {
|
||||
background-position: right 1em top 50%;
|
||||
}
|
||||
.ui.stackable.grid .ui.vertical.divider:after,
|
||||
.ui.grid .stackable.row .ui.vertical.divider:after {
|
||||
background-position: left 1em top 50%;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Icon
|
||||
---------------*/
|
||||
|
||||
.ui.divider > .icon {
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Header
|
||||
---------------*/
|
||||
|
||||
.ui.horizontal.divider[class*="left aligned"]:before {
|
||||
display: none;
|
||||
}
|
||||
.ui.horizontal.divider[class*="left aligned"]:after {
|
||||
width: 100%;
|
||||
}
|
||||
.ui.horizontal.divider[class*="right aligned"]:before {
|
||||
width: 100%;
|
||||
}
|
||||
.ui.horizontal.divider[class*="right aligned"]:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Variations
|
||||
*******************************/
|
||||
|
||||
|
||||
/*--------------
|
||||
Hidden
|
||||
---------------*/
|
||||
|
||||
.ui.hidden.divider {
|
||||
border-color: transparent !important;
|
||||
}
|
||||
.ui.hidden.divider:before,
|
||||
.ui.hidden.divider:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Inverted
|
||||
---------------*/
|
||||
|
||||
.ui.divider.inverted,
|
||||
.ui.vertical.inverted.divider,
|
||||
.ui.horizontal.inverted.divider {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.ui.divider.inverted,
|
||||
.ui.divider.inverted:after,
|
||||
.ui.divider.inverted:before {
|
||||
border-top-color: rgba(34, 36, 38, 0.15) !important;
|
||||
border-left-color: rgba(34, 36, 38, 0.15) !important;
|
||||
border-bottom-color: rgba(255, 255, 255, 0.15) !important;
|
||||
border-right-color: rgba(255, 255, 255, 0.15) !important;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Fitted
|
||||
---------------*/
|
||||
|
||||
.ui.fitted.divider {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Clearing
|
||||
---------------*/
|
||||
|
||||
.ui.clearing.divider {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Section
|
||||
---------------*/
|
||||
|
||||
.ui.section.divider {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/*--------------
|
||||
Sizes
|
||||
---------------*/
|
||||
|
||||
.ui.divider {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.ui.mini.divider {
|
||||
font-size: 0.78571429rem;
|
||||
}
|
||||
.ui.tiny.divider {
|
||||
font-size: 0.85714286rem;
|
||||
}
|
||||
.ui.small.divider {
|
||||
font-size: 0.92857143rem;
|
||||
}
|
||||
.ui.large.divider {
|
||||
font-size: 1.14285714rem;
|
||||
}
|
||||
.ui.big.divider {
|
||||
font-size: 1.28571429rem;
|
||||
}
|
||||
.ui.huge.divider {
|
||||
font-size: 1.42857143rem;
|
||||
}
|
||||
.ui.massive.divider {
|
||||
font-size: 1.71428571rem;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Theme Overrides
|
||||
*******************************/
|
||||
|
||||
.ui.horizontal.divider:before,
|
||||
.ui.horizontal.divider:after {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAACCAYAAACuTHuKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1OThBRDY4OUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1OThBRDY4QUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU5OEFENjg3Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5OEFENjg4Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VU513gAAADVJREFUeNrs0DENACAQBDBIWLGBJQby/mUcJn5sJXQmOQMAAAAAAJqt+2prAAAAAACg2xdgANk6BEVuJgyMAAAAAElFTkSuQmCC');
|
||||
}
|
||||
@media only screen and (max-width: 767px) {
|
||||
.ui.stackable.grid .ui.vertical.divider:before,
|
||||
.ui.grid .stackable.row .ui.vertical.divider:before,
|
||||
.ui.stackable.grid .ui.vertical.divider:after,
|
||||
.ui.grid .stackable.row .ui.vertical.divider:after {
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAACCAYAAACuTHuKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1OThBRDY4OUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1OThBRDY4QUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU5OEFENjg3Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5OEFENjg4Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VU513gAAADVJREFUeNrs0DENACAQBDBIWLGBJQby/mUcJn5sJXQmOQMAAAAAAJqt+2prAAAAAACg2xdgANk6BEVuJgyMAAAAAElFTkSuQmCC');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
Site Overrides
|
||||
*******************************/
|
||||
|
||||