angular-shepherd Tour Guide is not scrolling on clicking next page - html

Everything is working fine except scrolling when i click to the next element is taking their but is not scrolling to down for seeing purpose I have to scroll to down. I tried many ways but i could not able to fix please help me to fix this problem i gone through this link https://www.npmjs.com/package/angular-shepherd but no option . If anyone can help me that would be very great help for me.
<h2 class="second-element">London</h2>
<p class="third-element">London is the capital city of England. It is the most populous city in the United Kingdom, with a metropolitan area of over 13 million inhabitants.</p>
<div class="first-element">cool</div>
I have added this in my app.component.ts file code..
import { ShepherdService } from 'angular-shepherd';
export class AppComponent implements AfterViewInit {
constructor(private shepherdService: ShepherdService) { }
ngAfterViewInit() {
this.shepherdService.disableScroll = true;
this.shepherdService.modal = true;
this.shepherdService.confirmCancel = false;
this.shepherdService.addSteps([
{
id: 'intro',
options: {
attachTo: '.first-element bottom',
beforeShowPromise: function() {
return new Promise(function(resolve) {
setTimeout(function() {
window.scrollTo(0, 0);
resolve();
}, 500);
});
},
buttons: [
{
classes: 'shepherd-button-secondary',
text: 'Exit',
type: 'cancel'
},
{
classes: 'shepherd-button-primary',
text: 'Back',
type: 'back'
},
{
classes: 'shepherd-button-primary',
text: 'Next',
type: 'next'
}
],
classes: 'custom-class-name-1 custom-class-name-2',
highlightClass: 'highlight',
scrollTo: true,
showCancelLink: true,
title: 'Welcome to Rivet Labs',
text: ['This will help you toggle sidebar menu'],
when: {
show: () => {
console.log('show step');
},
hide: () => {
console.log('hide step');
}
}
}
},
{
here is 2nd id goes here
},
{
here is 3rd id goes here
}
}

I have solve my problem just we need to remove scroll function from next id to get to the element in default position. we have to remove this property //beforeShowPromise:function(){}// for next id.
beforeShowPromise: function() {
return new Promise(function(resolve) {
setTimeout(function() {
window.scrollTo(0, 0);
resolve();
}, 500);
});
},

Related

google is not defined when using vue2-google-maps

I am using Nuxt and vue2-google-maps but I do have the following error
module error: google is not defined
I read the official GitHub FAQ, so I used this.$gmapApiPromiseLazy().then().
But, I do have the aforementioned error.
getCurrentPositionandBathroom method is to get current position and search for convenience store around current position.
<template>
<v-app>
<v-btn class="blue white--text" #click="getCurrentPositionandBathroom"> search for bathroom! </v-btn>
<GmapMap
ref="mapRef"
:center="maplocation"
:zoom="15"
map-type-id="roadmap"
style="height: 300px; width: 900px"
>
<GmapMarker
v-for="m in markers"
:key="m.id"
:position="m.position"
:clickable="true"
:draggable="true"
:icon="m.icon"
#click="center = m.position"
/>
</GmapMap>
</v-app>
</template>
<script>
export default {
data() {
return {
maplocation: { lat: 35.6814366, lng: 139.767157 },
markers: [],
}
},
methods: {
getCurrentPositionandBathroom() {
if (process.client) {
if (!navigator.geolocation) {
alert('Japanese sentences')
return
}
navigator.geolocation.getCurrentPosition(this.success, this.error)
}
},
success(position) {
this.maplocation.lat = position.coords.latitude
this.maplocation.lng = position.coords.longitude
this.$gmapApiPromiseLazy().then(() => {
google.maps.event.addListenerOnce(
this.$refs.mapRef.$mapObject,
'idle',
function () {
this.getBathroom()
}.bind(this),
)
})
},
getBathroom() {
const map = this.$refs.mapRef.$mapObject
const placeService = new google.maps.places.PlacesService(map)
placeService.nearbySearch(
{
location: new google.maps.LatLng(this.maplocation.lat, this.maplocation.lng),
radius: 500,
type: ['convenience_store'],
},
function (results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
results.forEach((place) => {
const icon = {
url: place.icon,
scaledSize: new google.maps.Size(30, 30),
}
const marker = {
position: place.geometry.location,
icon,
title: place.name,
id: place.place_id,
}
this.markers.push(marker)
})
}
}.bind(this),
)
},
error(errorMessage) {
switch (errorMessage.code) {
case 1:
alert('Japanese sentences')
break
case 2:
alert('Japanese sentences')
break
case 3:
alert('Japanese sentences')
break
default:
alert('Japanese sentences')
break
}
},
},
}
</script>
What I should I do?
PS: I can see the Google Maps. In other words, Google Maps is displayed.
Alright, so there was quite a few configuration to do but I achieved to have a working map. Your this.getBathroom() method was not working for me, but this is related to the API or how you handle the logic I guess.
I basically followed the package README and it all went smooth at the end. Nothing special and google is available as explained in the following section:
If you need to gain access to the google object
Here is the final code of the .vue file
<template>
<div>
<button class="blue white--text" #click="getCurrentPositionandBathroom">
search for bathroom!
</button>
<GmapMap
ref="mapRef"
:center="maplocation"
:zoom="15"
map-type-id="roadmap"
style="height: 300px; width: 900px"
>
<GmapMarker
v-for="m in markers"
:key="m.id"
:position="m.position"
:clickable="true"
:draggable="true"
:icon="m.icon"
#click="center = m.position"
/>
</GmapMap>
</div>
</template>
<script>
import { gmapApi } from 'vue2-google-maps'
export default {
data() {
return {
maplocation: { lat: 35.6814366, lng: 139.767157 },
markers: [],
}
},
computed: {
google: gmapApi,
},
methods: {
getCurrentPositionandBathroom() {
if (process.client) {
if (!navigator.geolocation) {
alert('Japanese sentences')
return
}
navigator.geolocation.getCurrentPosition(this.success, this.error)
}
},
success(position) {
this.maplocation.lat = position.coords.latitude
this.maplocation.lng = position.coords.longitude
// this.$gmapApiPromiseLazy().then(() => { // not needed here anymore
this.google.maps.event.addListenerOnce(
this.$refs.mapRef.$mapObject,
'idle',
function () {
this.getBathroom()
}.bind(this)
)
// })
},
getBathroom() {
const map = this.$refs.mapRef.$mapObject
const placeService = new this.google.maps.places.PlacesService(map)
placeService.nearbySearch(
{
location: new this.google.maps.LatLng(
this.maplocation.lat,
this.maplocation.lng
),
radius: 500,
type: ['convenience_store'],
},
function (results, status) {
if (status === this.google.maps.places.PlacesServiceStatus.OK) {
results.forEach((place) => {
const icon = {
url: place.icon,
scaledSize: new this.google.maps.Size(30, 30),
}
const marker = {
position: place.geometry.location,
icon,
title: place.name,
id: place.place_id,
}
this.markers.push(marker)
})
}
}.bind(this)
)
},
error(errorMessage) {
switch (errorMessage.code) {
case 1:
alert('Japanese sentences')
break
case 2:
alert('Japanese sentences')
break
case 3:
alert('Japanese sentences')
break
default:
alert('Japanese sentences')
break
}
},
},
}
</script>
You can find the useful commit on my github repo here.
This is how it looks at the end, no errors so far.
PS: I didn't saw that you were using Vuetify, so I didn't bother bringing it back later on.

Vue: text field with typeahead

I want to make a text field with typeahead. I have a list of words and when you start typing them, a suggestion appears with the word(s). The thing is, it needs to be able to do it multiple times, every new word you type, it can show you a suggestion.
Anyone know how I can do this?
You can use vue-suggestion to accomplish this easily. Take a look at the demo to see if this suites you.
This is my implementation of App.vue which differs slightly.
<template>
<div>
{{ items }}
<vue-suggestion :items="results"
v-model="item"
:setLabel="setLabel"
:itemTemplate="itemTemplate"
#changed="inputChange"
#selected="itemSelected">
</vue-suggestion>
</div>
</template>
<script>
import itemTemplate from './item-template.vue';
export default {
data () {
return {
item: {},
items: [
{ id: 1, name: 'Golden Retriever'},
{ id: 2, name: 'Flying Squirrel'},
{ id: 3, name: 'Cat'},
{ id: 4, name: 'Catfish'},
{ id: 5, name: 'Squirrel'},
],
itemTemplate,
results: {}
}
},
methods: {
itemSelected (item) {
this.item = item;
},
setLabel (item) {
return item.name;
},
inputChange (text) {
// your search method
this.results = this.items.filter(item => item.name.includes(text));
// now `items` will be showed in the suggestion list
},
},
};
</script>

Add "Select All'' button to ion-select

I'm using ionic 4 and I want to set custom buttons on ion-select through interfaceOptions
HTML
<ion-item>
<ion-label>Lines</ion-label>
<ion-select multiple="true" [(ngModel)]="SelectedLines" [interfaceOptions]="customAlertOptions">
<ion-select-option [value]="line" *ngFor="let line of Lines">{{linea.Name}}</ion-select-option>
</ion-select>
</ion-item>
TS
customAlertOptions: any = {
buttons: [
{
text: 'Select All',
handler: (blah) => {
console.log('Select All Clicked');
},
{
text: 'No',
handler: (blah) => {
console.log('Confirm Cancel: blah');
}
}, {
text: 'Okay',
handler: () => {
console.log('Confirm Okay');
}
}
]
};
However, only the default buttons are showing (Ok and Cancel)
Docs say it should be possible
https://ionicframework.com/docs/api/select
I can see this has been reported for previous versions of Ionic
https://forum.ionicframework.com/t/custom-button-for-ion-select-through-selectoptions-not-working/157305
Is it possible to make this work on Ionic 4? Is there a workaround?
EDIT: I tried with the PopOver interface with the same results
What you are trying to do isn't possible from what I can see.
The documentation actually only says you can set the buttons text:
ion-select#select-buttons - Ionic Documentation
By default, the alert has two buttons: Cancel and OK. Each button's text can be customized using the cancelText and okText properties.
It doesn't say that the buttons can be customised.
You can pass in the interfaceOptions but its overridden later by the default button set:
https://github.com/ionic-team/ionic/blob/master/core/src/components/select/select.tsx#L339
The code looks like this:
const alertOpts: AlertOptions = {
mode,
...interfaceOptions,
header: interfaceOptions.header ? interfaceOptions.header : labelText,
inputs: this.createAlertInputs(this.childOpts, inputType),
buttons: [
{
text: this.cancelText,
role: 'cancel',
handler: () => {
this.ionCancel.emit();
}
},
{
text: this.okText,
handler: (selectedValues: any) => {
this.value = selectedValues;
}
}
],
cssClass: ['select-alert', interfaceOptions.cssClass,
(this.multiple ? 'multiple-select-alert' : 'single-select-alert')]
};
return alertController.create(alertOpts);
So as you can see the ...interfaceOptions, is passed in at the start, then the buttons are set to the defaults, with the only customisation options being the ok or cancel text.
i am working with AlertController from ionic and i can custom it, just take a look at my screen .
You just need to import AlertController and after you can do something like this for exemple :
home.page.ts
async addAlertHome(adresse: string, lat: string, lon: string) {
const alert = await this.alertController.create({
header: 'Ajouter aux favoris',
message: 'Êtes vous sûr de vouloir ajouter cette adresse à vos favoris ?',
buttons: [
{
text: 'Non',
role: 'cancel',
cssClass: 'secondary'
}, {
text: 'Oui',
handler: () => {
alert.dismiss().then(() => {
this.addFavoriteHome(adresse, lat, lon);
});
console.log('Confirm Okay');
}
}
]
});
await alert.present();
}
And use it where you want on html :
home.page.html
<ion-icon name="heart-empty" (click)="addAlert(location.display_name, location.lat, location.lon)" end>
</ion-icon>
And don't forget on your constructor :
public alertController: AlertController

How to let one component correspond with the other for a specific function

I've got a component where I click a color of a machine, when I change colors, the machine gets loaded with a different color inside a image carousel.
Now I also created a component in the bottom with a image gallery of the same machine. How can I make it that the image gallery also changes color when I click the color button in the top of the page?
Important notice: The two components are not in the same parent component but they do load in the same machine images already, so the methods are not wrong I believe.
this is the clickable color button:
<li
v-for="(color, index) in machine.content[0].machine_colors"
:key="color.color_slug"
v-if="color.inStock"
v-on:click="selectColor(index)"
v-bind:class="{ active: (color.color_slug === selectedColor.color_slug)}">
<img v-bind:src="color.color_dash">
</li>
this is the component that changes color:
<div class="product__carousel">
<Carousel showIcon v-if="selectedColor" :machineColor="selectedColor"/> <!-- Image carousel gets loaded in -->
</div>
and the component that needs to change color but does not:
<div id="tab-two-panel" class="panel">
<footerGallery v-if="selectedColor && machine" :machineColor="selectedColor"/>
</div>
Heres the script of the partent component:
export default {
name: 'aboutMachine',
components: {
Collapse,
footerGallery,
},
data() {
return{
selectedColor: this.getMachineColorContent(),
}
},
props: {
main: {
default () {
return {};
},
},
machine: {
default () {
return {};
},
},
},
methods: {
getMachineColorContent() {
if (this.selectedColor) {
return null;
}
return this.machine.content[0].machine_colors[0];
},
selectColor(index) {
this.selectedColor = this.machine.content[0].machine_colors[index];
},
},
}
and the component itself:
export default {
name: 'footerGallery',
props: {
showIcon: Boolean,
machineColor: {
default () {
return {};
},
},
},
data() {
return {
highLightedThumbIndex: 0,
isActive: undefined,
};
},
created() {
this.highLightedThumbIndex = this.highLightedThumbIndex || 0;
},
methods: {
selectThumb(index) {
this.highLightedThumbIndex = index;
},
},
};
This is my main.js
import Vue from 'vue';
import VueYouTubeEmbed from 'vue-youtube-embed'
import FontAwesome from './libs/fa';
import App from './App';
const eventHub = new Vue();
Vue.use(VueYouTubeEmbed);
Vue.component('font-awesome-icon', FontAwesome);
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>',
});
I would use events to accomplish this. The migration guide to Vue2 has a good short explanation of how to do simple event routing without using a full Vuex solution. In your case, you would declare a global event hub in one of your js files:
var eventHub = new Vue();
In your selectColor method you would emit the index selected:
selectColor(index) {
this.selectedColor = this.machine.content[0].machine_colors[index];
eventHub.$emit("select-color",index);
}
And in the footer, you would register a listener for the select-color event that calls selectThumb with the payload of the event (which is the selected index):
created() {
this.highLightedThumbIndex = this.highLightedThumbIndex || 0;
eventHub.$on("select-color",this.selectThumb);
}

Jquery Mobile when redirecting or changing url, pages does not have any css

I am working with a backbone, jquery mobile, express app. Everything looks fine when the app starts and works correctly, however, when I click a link or change the url the html renders correctly but no jquery mobile magic appears. It only renders in the login part with a header and footer and format, but when the url changes and I come back, the page loses its css or jquery mobile magic.
define(['views/index', 'views/register', 'views/login', 'views/forgotpassword', 'views/profile',
'views/vinbookDoc', 'models/Account', 'models/Vinbook', 'models/vinBooksCollection'],
function(IndexView, RegisterView, LoginView, ForgotPasswordView, ProfileView,
vinbookDocView, Account, Vinbook, vinBooksCollection) {
var AppRouter = Backbone.Router.extend({
currentView: null,
routes: {
"index": "index",
"login": "login",
"desk/:id": "desk",
"profile/:id": "profile",
"register": "register",
"forgotpassword": "forgotpassword",
"vinbook/:id": "showVinbook"
},
initialize: function(){
$('.back').live('click', function(event) {
window.history.back();
return false;
});
this.firstPage = true;
},
showVinbook: function(id) {
var getCollection = new vinBooksCollection();
getCollection.url = '/accounts/me/vinbook';
this.changeView( new vinbookDocView({
collection: getCollection,
id: id
}));
getCollection.fetch();
},
changeView: function(page) {
this.currentView = page;
$(this.currentView.el).attr('data-role', 'page');
this.currentView.render();
$('body').append($(this.currentView.el));
var transition = $.mobile.defaultPageTransition;
// We don't want to slide the first page
if (this.firstPage) {
transition = 'none';
this.firstPage = false;
}
$.mobile.changePage($(this.currentView.el), {changeHash:false, transition: transition});
},
index: function() {
this.changeView(new IndexView() );
},
desk: function (id){
var model = new Account({id:id});
this.changeView(new ProfileView({model:model}));
model.fetch({ error: function(response){ console.log ('error'+JSON.stringify(response)); } });
console.log('works');
},
profile: function (id){
this.changeView(new IndexView() );
},
login: function() {
this.changeView(new LoginView());
},
forgotpassword: function() {
this.changeView(new ForgotPasswordView());
},
register: function() {
this.changeView(new RegisterView());
}
});
return new AppRouter();
});
require
require.config({
paths: {
jQuery: '/js/libs/jquery',
jQueryUIL: '/js/libs/jqueryUI',
jQueryMobile: '/js/libs/jqueryMobile',
Underscore: '/js/libs/underscore',
Backbone: '/js/libs/backbone',
models: 'models',
text: '/js/libs/text',
templates: '../templates',
jqm: '/js/jqm-config',
AppView: '/js/AppView'
},
shim: {
'jQueryMobile': ['jQuery', 'jqm' ],
'jQueryUIL': ['jQuery'],
'Backbone': ['Underscore', 'jQuery', 'jQueryMobile', 'jQueryUIL'],
'AppView': ['Backbone']
}
});
require(['AppView' ], function(AppView) {
AppView.initialize();
});
login
define(['AppView','text!templates/login.html'], function(AppView, loginTemplate) {
window.loginView = AppView.extend({
requireLogin: false,
el: $('#content'),
events: {
"submit form": "login"
},
initialize: function (){
$.get('/login', {}, function(data){});
},
login: function() {
$.post('/login', {
email: $('input[name=email]').val(),
password: $('input[name=password]').val()
},
function(data) {
console.log(data);
if (!data.error){window.location.replace('#desk/me');}
}).error(function(){
$("#error").text('Unable to login.');
$("#error").slideDown();
});
return false;
},
render: function() {
this.$el.html(loginTemplate);
$("#error").hide();
return this;
}
});
return loginView;
});
Just some more details:
When I change from page or the url to another page, a flash of the rendered website appears and then the css or design disappears.
I think this can solve your problem:
$(document).bind('pagechange', function() {
$('.ui-page-active .ui-listview').listview('refresh');
$('.ui-page-active :jqmData(role=content)').trigger('create');
});