mirror of
https://github.com/Spythere/pojazdownik.git
synced 2026-05-03 05:18:10 +00:00
realne zestawienia: zapamiętywanie pozycji scrolla; ostatni wybrany pociąg
This commit is contained in:
@@ -5,7 +5,9 @@
|
|||||||
<div class="card_content">
|
<div class="card_content">
|
||||||
<div class="card_nav">
|
<div class="card_nav">
|
||||||
<div class="top-pane">
|
<div class="top-pane">
|
||||||
<h1>ZESTAWIENIA REALNE by <a href="https://td2.info.pl/profile/?u=17708" target="_blank">Railtrains997</a></h1>
|
<h1>
|
||||||
|
ZESTAWIENIA REALNE by <a href="https://td2.info.pl/profile/?u=17708" target="_blank">Railtrains997</a>
|
||||||
|
</h1>
|
||||||
<button class="btn exit-btn" @click="store.isRealStockListCardOpen = false">⨯</button>
|
<button class="btn exit-btn" @click="store.isRealStockListCardOpen = false">⨯</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -23,34 +25,32 @@
|
|||||||
</option>
|
</option>
|
||||||
</datalist>
|
</datalist>
|
||||||
|
|
||||||
<input list="readyStockStringList" placeholder="Szukaj zestawienia po pojazdach" />
|
<input
|
||||||
|
list="readyStockStringList"
|
||||||
|
v-model="searchedReadyStockString"
|
||||||
|
placeholder="Szukaj zestawienia po pojazdach"
|
||||||
|
/>
|
||||||
|
|
||||||
<datalist id="readyStockStringList">
|
<datalist id="readyStockStringList">
|
||||||
<option v-for="stock in store.readyStockList" :value="stock.stockString">
|
<option v-for="stock in store.readyStockList" :value="stock.stockString">{{stock.stockString}}</option>
|
||||||
{{ stock.type }} {{ stock.number }} {{ stock.name }}
|
|
||||||
</option>
|
|
||||||
</datalist>
|
</datalist>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="card_list" ref="list" @scroll="onListScroll">
|
<ul class="card_list" ref="list" @scroll="onListScroll">
|
||||||
<li v-for="(rStock, i) in computedReadyStockList" :key="i">
|
<li
|
||||||
<div
|
v-for="rStock in computedReadyStockList"
|
||||||
class="desc"
|
:key="rStock.stockId"
|
||||||
tabindex="0"
|
:data-last-selected="store.chosenRealStockName === rStock.stockId"
|
||||||
@click="chooseStock(rStock.stockString)"
|
>
|
||||||
@keydown.enter="chooseStock(rStock.stockString)"
|
<div class="stock-title" tabindex="0" @click="chooseStock(rStock)" @keydown.enter="chooseStock(rStock)">
|
||||||
>
|
|
||||||
<img :src="getIconURL(rStock.type)" :alt="rStock.type" />
|
<img :src="getIconURL(rStock.type)" :alt="rStock.type" />
|
||||||
<b class="text--accent" style="margin-left: 5px"> {{ rStock.name }}</b>
|
<b class="text--accent" style="margin-left: 5px"> {{ rStock.name }}</b>
|
||||||
<div>{{ rStock.number }}</div>
|
<div>{{ rStock.number }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="thumbnails" ref="thumbnailsRef">
|
<div class="stock-thumbnails" ref="thumbnailsRef">
|
||||||
<div v-for="stockItem in rStock.stockString.split(';')">
|
<div v-for="stockItem in rStock.stockString.split(';')">
|
||||||
<!-- rStock.stockString.split(';') -->
|
|
||||||
<!-- <span> -->
|
|
||||||
<!-- <span>{{ stockItem }}</span> -->
|
|
||||||
<div class="thumbnail_container">
|
<div class="thumbnail_container">
|
||||||
<img
|
<img
|
||||||
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${stockItem}.png`"
|
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${stockItem}.png`"
|
||||||
@@ -59,11 +59,7 @@
|
|||||||
@error="onStockItemError"
|
@error="onStockItemError"
|
||||||
@load="e => (e.target as HTMLElement).style.opacity = '1'"
|
@load="e => (e.target as HTMLElement).style.opacity = '1'"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- <img src="images/car-passenger-unknown.png" alt=""> -->
|
|
||||||
</div>
|
</div>
|
||||||
<!-- <img @error="e => (e.target as HTMLImageElement).src = `images/car-passenger-unknown.png`" /> -->
|
|
||||||
<!-- </span> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -81,6 +77,8 @@ import { useStore } from '../../store';
|
|||||||
import imageMixin from '../../mixins/imageMixin';
|
import imageMixin from '../../mixins/imageMixin';
|
||||||
import stockMixin from '../../mixins/stockMixin';
|
import stockMixin from '../../mixins/stockMixin';
|
||||||
|
|
||||||
|
import { IReadyStockItem } from '../../types';
|
||||||
|
|
||||||
interface ResponseJSONData {
|
interface ResponseJSONData {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
}
|
}
|
||||||
@@ -89,14 +87,15 @@ export default defineComponent({
|
|||||||
mixins: [imageMixin, stockMixin],
|
mixins: [imageMixin, stockMixin],
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
store: useStore(),
|
||||||
responseStatus: 'loading',
|
responseStatus: 'loading',
|
||||||
isMobile: 'ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/) ? true : false,
|
isMobile: 'ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/) ? true : false,
|
||||||
observer: null as IntersectionObserver | null,
|
observer: null as IntersectionObserver | null,
|
||||||
searchedReadyStockName: '',
|
searchedReadyStockName: '',
|
||||||
store: useStore(),
|
searchedReadyStockString: '',
|
||||||
visibleIndexesTo: 0,
|
visibleIndexesTo: 0,
|
||||||
lastChecked: null,
|
lastSelectedStockId: null as string | null,
|
||||||
scrollY: 0,
|
scrollTop: 0,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@@ -106,10 +105,11 @@ export default defineComponent({
|
|||||||
|
|
||||||
activated() {
|
activated() {
|
||||||
(this.$refs['search'] as HTMLInputElement).focus();
|
(this.$refs['search'] as HTMLInputElement).focus();
|
||||||
},
|
|
||||||
|
|
||||||
deactivated() {
|
(this.$refs['list'] as HTMLElement).scrollTo({
|
||||||
console.log((this.$refs['list'] as HTMLElement).scrollTop);
|
top: this.scrollTop,
|
||||||
|
behavior: 'auto',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
@@ -117,7 +117,11 @@ export default defineComponent({
|
|||||||
if (this.searchedReadyStockName == null) return this.store.readyStockList;
|
if (this.searchedReadyStockName == null) return this.store.readyStockList;
|
||||||
|
|
||||||
return this.store.readyStockList
|
return this.store.readyStockList
|
||||||
.filter((rs) => rs.name.toLocaleLowerCase().includes(this.searchedReadyStockName.toLocaleLowerCase()))
|
.filter(
|
||||||
|
(rs) =>
|
||||||
|
rs.name.toLocaleLowerCase().includes(this.searchedReadyStockName.toLocaleLowerCase()) &&
|
||||||
|
rs.stockString.includes(this.searchedReadyStockString)
|
||||||
|
)
|
||||||
.filter((_, i) => i <= this.visibleIndexesTo);
|
.filter((_, i) => i <= this.visibleIndexesTo);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -142,11 +146,16 @@ export default defineComponent({
|
|||||||
for (let stockKey in readyStockJSONData) {
|
for (let stockKey in readyStockJSONData) {
|
||||||
const [type, number, ...name] = stockKey.split(' ');
|
const [type, number, ...name] = stockKey.split(' ');
|
||||||
|
|
||||||
this.store.readyStockList.push({
|
const obj = {
|
||||||
type,
|
|
||||||
number: number.replace(/_/g, '/'),
|
number: number.replace(/_/g, '/'),
|
||||||
name: name.join(' '),
|
name: name.join(' '),
|
||||||
stockString: readyStockJSONData[stockKey],
|
stockString: readyStockJSONData[stockKey],
|
||||||
|
type,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.store.readyStockList.push({
|
||||||
|
...obj,
|
||||||
|
stockId: `${obj.type} ${obj.number} ${obj.name}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,10 +164,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
mountObserver() {
|
mountObserver() {
|
||||||
this.observer = new IntersectionObserver((entries) => {
|
this.observer = new IntersectionObserver((entries) => {
|
||||||
// Is the entry visible?
|
if (entries[0].intersectionRatio > 0) this.visibleIndexesTo += 20;
|
||||||
if (entries[0].intersectionRatio > 0) {
|
|
||||||
this.visibleIndexesTo += 20;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.observer.observe(this.$refs['bottom'] as HTMLElement);
|
this.observer.observe(this.$refs['bottom'] as HTMLElement);
|
||||||
@@ -168,8 +174,9 @@ export default defineComponent({
|
|||||||
return new URL(`./dir/${name}.png`, import.meta.url).href;
|
return new URL(`./dir/${name}.png`, import.meta.url).href;
|
||||||
},
|
},
|
||||||
|
|
||||||
chooseStock(stockString: string) {
|
chooseStock(stockItem: IReadyStockItem) {
|
||||||
this.loadStockFromString(stockString);
|
this.loadStockFromString(stockItem.stockString);
|
||||||
|
this.lastSelectedStockId = stockItem.stockId;
|
||||||
this.store.isRealStockListCardOpen = false;
|
this.store.isRealStockListCardOpen = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -182,6 +189,8 @@ export default defineComponent({
|
|||||||
onListScroll(e: Event) {
|
onListScroll(e: Event) {
|
||||||
const listElement = e.target as HTMLElement;
|
const listElement = e.target as HTMLElement;
|
||||||
const scrollTop = listElement.scrollTop;
|
const scrollTop = listElement.scrollTop;
|
||||||
|
|
||||||
|
this.scrollTop = scrollTop;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -221,6 +230,7 @@ export default defineComponent({
|
|||||||
color: #aaa;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-sticky {
|
.top-sticky {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -247,8 +257,13 @@ ul {
|
|||||||
grid-template-columns: 1fr 2fr;
|
grid-template-columns: 1fr 2fr;
|
||||||
background: #2b2b2b;
|
background: #2b2b2b;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
padding: 0.1em;
|
||||||
|
|
||||||
.desc {
|
&[data-last-selected='true'] .stock-title {
|
||||||
|
border: 1px solid $accentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stock-title {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
@@ -257,22 +272,13 @@ ul {
|
|||||||
height: 0.85em;
|
height: 0.85em;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
|
||||||
color: #999;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #222;
|
background: #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: 1px solid white;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnails {
|
.stock-thumbnails {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
|
||||||
@@ -280,27 +286,10 @@ ul {
|
|||||||
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
|
||||||
// img {
|
|
||||||
// // width: 150px;
|
|
||||||
// height: 100%;
|
|
||||||
// max-height: 20px;
|
|
||||||
// vertical-align: middle;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnail_container {
|
.thumbnail_container img {
|
||||||
// position: relative;
|
height: 30px;
|
||||||
// width: 100%;
|
|
||||||
// height: 0;
|
|
||||||
|
|
||||||
img {
|
|
||||||
// position: absolute;
|
|
||||||
// top: 0;
|
|
||||||
// left: 0;
|
|
||||||
// width: 100%;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ export interface IStock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IReadyStockItem {
|
export interface IReadyStockItem {
|
||||||
|
stockId: string;
|
||||||
stockString: string;
|
stockString: string;
|
||||||
type: string;
|
type: string;
|
||||||
number: string;
|
number: string;
|
||||||
|
|||||||
@@ -154,9 +154,7 @@ export function chosenRealStock(state: IStore) {
|
|||||||
|
|
||||||
const realStockObj = state.readyStockList.find((readyStock) => readyStock.stockString == currentStockString);
|
const realStockObj = state.readyStockList.find((readyStock) => readyStock.stockString == currentStockString);
|
||||||
|
|
||||||
state.chosenRealStockName = realStockObj
|
state.chosenRealStockName = realStockObj?.stockId ?? undefined;
|
||||||
? `${realStockObj.type} ${realStockObj.number} ${realStockObj.name}`
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
return realStockObj;
|
return realStockObj;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user