I'm using the wonderful vue-scrollto along with bootstrap. It's working great and lands perfectly when viewed on the desktop. On mobile however, the heading is off the top. I know from previous experience with dynamic scrolling that padding the header is the way to go, which works on one section in my site but not on another.
I thought perhaps it was because I'm loading content dynamically and adding content to the dom, but doesn't seem to be the issue since other, static sections have the same issue. It does seem to be when a content section is taller than the viewport. I was originally targeting the id of the container for the section but changed it to the id of the heading with no change.
If I add offset it can help but inconsistently - works on the about section but the locations section is still way off. I figured it would just scroll the top of the container i'm targeting to the top of the page, but that doesn't seem to be what's happening.
Example link:
<li class="nav-item">
<a class="nav-link nav-btn" href="#" v-scroll-to="'#title-about'" data-toggle="collapse">About</a>
</li>
In my app.js:
Vue.use(VueScrollTo, {
container: "body",
offset: -100
})
You can see it in action here: lovelaundry
It seems as though any section that is taller than the viewport doesn't land right - like it positions in the vertical center rather than scrolling to place the top of the targeted element at the top of the viewport, which would be ideal.
I figured out a solution - not very elegant and I doubt it's the best, but it does work and gives me pretty precise control. I created a root method like so:
scrollTo(target, offset1 = -100, offset2 = -450) {
//viewport break is 991, offset1 is when greater then 991 for larger viewports, offset2 for smaller
console.log('1: ' + offset1 + ' | ' + '2: ' + offset2);
if (window.innerWidth > 991) {
this.os = offset1;
} else {
this.os = offset2;
}
console.log(this.os);
var options = {
container: 'body',
offset: this.os
}
var cancelScroll = VueScrollTo.scrollTo(target, 500, options);
},
Then I either call this directly from HTML through my laravel blade template:
<a class="nav-link nav-btn" href="#" v-on:click="scrollTo('#title-about', -100, -250)" data-toggle="collapse">About</a>
Or emit it up to the parent from a component:
changeLocation(location) {
this.$eventHub.$emit('location-loaded', location);
this.$eventHub.$emit('scroll-to', '#title-locations', -100, -450);
},
In the template:
<a v-for="loc in locations" v-on:click="changeLocation(loc)" class="dropdown-item nav-btn" v-bind:class="{ active: loc.id == location.id }">{{ loc.name }}</a>
I still don't quite get how it's working - I have to use different offset values to make it land in the right place if I'm linking from the top of the page or the bottom.
A more elegant solution would be to make the <b-navbar> fixed to top and offset your content div:
<b-navbar class="fixed-navbar"> ... </b-navbar>
.fixed-navbar {
top: 0;
position: fixed;
width: 100%;
}
To make your navbar not to overlap your content add margin to nuxt element
<Nuxt style="margin-top: 56px" />
Also don't forget to add offset for your vue-scrollTo in your config
['vue-scrollto/nuxt', { offset: -56 }]
Related
I'm trying to configure a nice footer on a pdf document I'm generating using Flying Saucer.
But I'm having problems getting the page number and page count in a nice position.
Consider this bit of css:
div#page-footer {
position : running(footer);
// .. more styling .. //
}
div.page-number:before {
content: counter(page);
}
Using this bit of html will not give me a page number:
<div id="page-footer">
<div class="page-number"></div>
</div>
The only way I manage to get a page number if I move the class a level up.
<div id="page-footer" class="page-number">
</div>
But this does not allow me to add additional content in the footer or makes it really difficult to apply styling. I could add a separate footer just for the page number, but it would be quite hard to get the position just right.
Is there a way to get page number + page count in a footer that also contains other elements and styling?
Extra notes:
I simplified the footer a bit, in the original there is more in there, but even this simple example it is giving problems.
using span or div for the element does not make a difference.
You should use the id instead of the class to identify the div containing the page number.
This will work:
div#page-number:before {
content: counter(page);
}
<div id="page-footer">
<div id="page-number"></div>
</div>
I'm using Algolia instantsearch.js for search, and to display my result page, I'm using Bootstrap 3, and I'd like hits to be displayed in 3 columns:
qry | hit1 | hit2
| hit3 | hit4
| hit5 | hit6
(where qry = the search query input widget)
etc..
If it's mobile, it should display as:
qry
hit1
hit2
hit3
etc.
Can someone help me with the html/css I can use to implement this?
Thanks!
Basically, you want to use bootstrap rows and grid layout col-{xs,sm,md,lg}-X (More info about the grid layout here).
One interesting property with bootstrap is that if you declare a block as being col-YY-X, if the screen width is under the dimensions YY is associated with, it automatically expands to the full width.
instantsearch.js's widgets expose a cssClasses parameter that allows you to customize the classes of the underlying markup.
To easily do two columns, all you need to do is declare the root element of the cssClasses as being a .row, and each result as a .col-sm-6 (or .col-md-6 or .col-lg-6 depending on which screen size you want it to apply).
By combining them, you can have some really interesting layouts.
See this JSFiddle
Here, I've extended a bit the idea. Try to resize the view, and you'll see that it automatically picks a number of results to display per line depending on the width by combining multiple col-YY-X classes on the hit widget.
search.addWidget(
instantsearch.widgets.hits({
container: '#hits',
templates: {
empty: 'No results',
item: '<div class="hit">{{title}}</div>'
},
hitsPerPage: 6,
cssClasses: {
root: 'row',
item: 'col-lg-3 col-md-4 col-sm-6'
}
})
);
As you can see, I've also added an inner class to the item template to be able to use the item as a wrapper with padding inside to avoid having the hits glued to each other. I apply the border to the inner element, because adding margins to bootstrap grid elements is not the right solution.
The layout itself is really simple, you can just nest rows together:
<div class="container-fluid">
<div id="search" class="row">
<div class="col-sm-4">
<div id="input"></div>
</div>
<div class="col-sm-8">
<div id="hits" class="row">
</div>
</div>
</div>
</div>
Wanted to use this 'item' example:
http://codepen.io/dimsemenov/pen/sHoxp
but instead of having one button, I'd like to have multiple buttons for each inline element (like a gallery).
For example, How would I create a second button that would open data array item 2 (paul irish)? Is there a way to specify from the button link? thanks!
I had to do something similar and had no idea how to do it so hopefully this helps someone later.
All my modals were inline but I also needed a list for each item on the page so you could click on the link and it would open at Item 2 or 3 etc..but still allow you to navigate through the gallery. I based my code off this http://codepen.io/dimsemenov/pen/zvLny and added the additional parts for the id's.
Basically you just have to put a data attribute e.g data-slideid on the individual links and pass that through when you open magnific. After you set everything you can specify which item it opens at by passing through the value from data-slideid. If anyone has a better solution i'd love to know!
Check out my below
<div id="gallery1" class="mfp-hide">
<div class="slide" data-slideid="0">slide 1</div>
<div class="slide" data-slideid="1">slide 2</div>
<div class="slide" data-slideid="2">slide 3</div>
</div>
// single link opens gallery starting at first slide
<p>view gallery</p>
// individual links opens gallery starting at relevant slide
Slide1
Slide2
Slide3
$('.open-gallery-link').click(function() {
var itemNum = $(this).data("slideid"); // get the id
var items = [];
$( $(this).attr('href') ).find('.slide').each(function() {
items.push( {
src: $(this)
} );
});
$.magnificPopup.open({
items:items,
gallery: {
enabled: true
}
},itemNum); // set it in here
});
I have, essentially, an unlimited number of containers with dynamic ids and a dynamic menu to load each containers content. I have done this with static id's (but still seems such a heavy use) but do not know where to go to use dynamic.
When a nav link (from .img_select) is clicked it shows the corresponding div and hides all others in the group. It also updates the class of the menu items so the clicked item becomes selected, and the remaining become unselected.
<div id="pf1_1">
My content for pf1_1 container goes here
</div>
<div id="pf1_2">
My content for pf1_2 container goes here
</div>
<!-- This could have a dozen+ or more divs, or only 1 //-->
<p class="img_select"><span class="pf_current" id="pfc1_1">1-1</span> <span class="pf_next" id="pfc1_2">1-2</span></p>
<div id="pf2_1">
My content for pf2_1 container goes here
</div>
<div id="pf2_2">
My content for pf2_2 container goes here
</div>
<div id="pf2_3">
My content for pf2_3 container goes here
</div>
<!-- This could have a dozen+ or more divs or only 1 //-->
<p class="img_select"><span class="pf_current" id="pfc2_1">2-1</span> <span class="pf_next" id="pfc2_2">2-2</span> <span class="pf_next" id="pfc2_3">2-3</span></p>
the jquery I would like to create dynamically something similar to this
<script>
$(document).ready(function(){
$("#pf1_2").hide();
$("#pf2_2").hide();
$("#pf2_3").hide();
$('#pfc1_1').click(function(){
$("#pf1_2").hide('fast');
$("#pf1_1").show('fast');
$("#pfc1_1").removeClass("pf_next").addClass("pf_current");
$("#pfc1_2").removeClass("pf_current").addClass("pf_next");
});
$('#pfc1_2').click(function(){
$("#pf1_1").hide('fast');
$("#pf1_2").show('fast');
$("#pfc1_2").removeClass("pf_next").addClass("pf_current");
$("#pfc1_1").removeClass("pf_current").addClass("pf_next");
});
$('#pfc2_1').click(function(){
$("#pf2_2").hide('fast');
$("#pf2_3").hide('fast');
$("#pf2_1").show('fast');
$("#pfc2_1").removeClass("pf_next").addClass("pf_current");
$("#pfc2_2").removeClass("pf_current").addClass("pf_next");
$("#pfc2_3").removeClass("pf_current").addClass("pf_next");
});
$('#pfc2_2').click(function(){
$("#pf2_1").hide('fast');
$("#pf2_3").hide('fast');
$("#pf2_2").show('fast');
$("#pfc2_2").removeClass("pf_next").addClass("pf_current");
$("#pfc2_1").removeClass("pf_current").addClass("pf_next");
$("#pfc2_3").removeClass("pf_current").addClass("pf_next");
});
$('#pfc2_3').click(function(){
$("#pf2_2").hide('fast');
$("#pf2_1").hide('fast');
$("#pf2_3").show('fast');
$("#pfc2_3").removeClass("pf_next").addClass("pf_current");
$("#pfc2_2").removeClass("pf_current").addClass("pf_next");
$("#pfc2_1").removeClass("pf_current").addClass("pf_next");
});
});
</script>
If you can point me in the right direction, be much appreciated, thank you.
Seeing as I found a way, not saying was right way, but it worked, I wanted to share it with you.
I would like to point out it didn't take 2 months to sort a solution, just 2 months to post it here.
To combat this;
$("#pf1_2").hide();
$("#pf2_2").hide();
$("#pf2_3").hide();
I used this;
$("div[id^=pf_]").hide();
$("div[id$=_1]").show();
first it hides all id's starting with pf_
then it shows only the first by matching id ending in _1
To combat this;
$('#pfc1_1').click(function(){
$("#pf1_2").hide('fast');
$("#pf1_1").show('fast');
$("#pfc1_1").removeClass("pf_next").addClass("pf_current");
$("#pfc1_2").removeClass("pf_current").addClass("pf_next");
});
// etc.....
I used this;
$('span[id^=pfc_]').live("click", function(e) {
e.preventDefault();
var id = $(this).attr('id').split('_');
var classname = $(this).attr('class');
var navwidth = $("div[id^=pf_"+id[1]+"_"+id[2]+"]").width();
if(classname != 'pf_current'){
$("span[id^=pfc_"+id[1]+"_]").removeClass("pf_current").addClass("pf_next");
$("span[id^=pfc_"+id[1]+"_"+id[2]+"]").removeClass("pf_next").addClass("pf_current");
// change portfolio item
$("div[id^=pf_"+id[1]+"_]").hide();
$("div[id^=pf_"+id[1]+"_"+id[2]+"]").delay('5').show();
}
});
Hope this helps someone else
I have a templated custom widget that inherits from dijit.layout._LayoutWidget, dijit._Container, and dijit._Templated which gives my widget native Widget support for resizing, etc. All I need is a TabContainer, which is sized to the size of widget. Here is my widget.
<div dojoAttachPoint="containerNode">
<div dojoType="dijit.layout.TabContainer" tabPosition="top" style="width:100%;height:100%" >
<div dojoType="dijit.layout.ContentPane" title="tab" selected="true">
hello
</div>
</div>
</div>
Everything looks fine but I get a weird TabList.
I looked into the problem. All the pieces of the widget and TabContainer have the correct width and height values. Only The tablist has a loooong width (50'000 something pixels wide): I have read about similar issues such as this one: http://bugs.dojotoolkit.org/ticket/10495, but in my case all the elements have correct width and length. I have no idea how does tablist get this long width.
I have also tried many ways of adding and removing style="width:100%;height:100;" for the parent container and its parents. But none of the configurations fixed the problem.
Is there a way to fix this problem?
Just in case someone is looking for the solution, I had the same problem, and came to this question. Though I looked at the bug reports, it didn't apply in my case, I was not embedding tabcontainer inside table or setting doLayout to false. I tried setting tabcontroller but that didn't work either. Finally after debuggin, turns out you have to provide 'resize' method in your widget and resize tabcontainer inside it in the following way
widgetTemplate = '... ' + //Our tabcontainer declaration
'<div dojoAttachPoint="containerNode">' +
'<div dojoAttachPoint="widgetTab" dojoType="dijit.layout.TabContainer"' + 'style="width:100%;height:100%" >' +
'<div dojoType="dijit.layout.ContentPane" title="tab" selected="true">hello</div></div></div>' +
'...' //Rest Of template declaration
//Since we are embedding widget inside template we need _WidgetsInTemplateMixin
dojo.declare("MyWidget", [dijit._Widget, dijit._TemplatedMixin,dijit._WidgetsInTemplateMixin], {
templateString: widgetTemplate,
.... //Rest of functions
resize: function(){
this.containerNode.widgetTab.resize() //Resize tabcontainer
}
});
Hope this helps
Try to add attribute to your TabContainer:
<div dojoType="dijit.layout.TabContainer" controllerWidget="dijit.layout.TabController" ... >
http://bugs.dojotoolkit.org/ticket/10113#comment:11
Just rewrite your css like this:
div[class="dijitTabListWrapper dijitTabContainerTopNone dijitAlignClient"]{
height: 30px !important;
}
#-moz-document url-prefix() {
div[class="dijitTabListWrapper dijitTabContainerTopNone dijitAlignClient"]{
height: 31px !important;
}
}
If you want to remove the first one : "useMenu : false"
If you want to remove the second and the third : "useSlider : false"