How to enable a sticky menu within the Ionic framework? - javascript

I have a view where I need to implement a sticky menu inside of the Ionic framework.
Looking for an Angular not jQuery solution I found ngSticky. Great library works perfect, the problem however is that it won't work inside of the Ionic directive <ion-content>.
I asked a previous question about it here, and then figured out what was going on:
Because the parent container that ion-content creates has the following style on it:
<div class="scroll" style="transform: translate3d(0px, 0px, 0px) scale(1);">
It's a fix for an iPad scrolling bug as described here.
So I can't remove that style and removing it would involve making changes to the core ionic.bundle.js file anyways.
The only thing I can think of now at the moment, is to write some code to detect when the sticky header hits the top, then remove that block of HTML out of ion-content and replace it above the ion-content container.
Is there any other way around this?
Here is a Plunker http://plnkr.co/edit/DiVfOzjJevSFOtVitYty?p=preview
There is a jQuery hack in place that removes the style tag so you can see how it should work.

I wanted to create something similar.
I had an image on top and a button below. As I'm scrolling down the page I wanted the button to stay on top.
(sticky menu === sticky button === all the same)
Code below isn't working reliably and is full of hacks so I'm hesitant to share it... In fact I've actually removed it from the codebase, posting here for illustrational purposes only:
// INITIALISATION SETUP
var $button = $(".button-middle-wrapper");
var buttonOffset;
var _measureOffset = function() {
buttonOffset = $button.offset().top;
};
setTimeout(_measureOffset, 500); // HACK: during initialisation image is not loaded - therefore image offset is not correct - wait for image to load?
$(window).resize(_measureOffset);
// METHOD AVAILABLE ON THE SCOPE
$scope.fixButtonToTop = function() {
var scrollPosition = $ionicScrollDelegate.getScrollPosition().top;
if (scrollPosition > buttonOffset - 30) {
$button.css({"top": scrollPosition + 30}); // normally it is enough to set position to "fixed" - in Ionic case we do not scroll browser window - we do tranlations and setting positions - so we manually calculate position
} else {
$button.css({"top": ""});
}
};
And then in the view: <ion-content on-scroll="fixButtonToTop">
Not only the code is terrible but I've also committed one of the common mistakes described here: https://www.toptal.com/ionic/most-common-ionic-development-mistakes
Common Mistake #8: Binding Events to onscroll, and Forgetting About requestAnimationFrame

I know its not a good solution, but I'd simply go for applying CSS rule with !important to override the current style
.pane {
transform: none !important;
-webkit-transform: none; /* Safari and Chrome */
-moz-transform: none; /* Firefox */
-ms-transform: none; /* IE 9 */
-o-transform: none; /* Opera */
}
Plunkr Here

Related

How to input a CSS class with JavaScript to affect another function

I have gone at a lot of informative sites in order to find answer but no luck so far. Thus now asking here.
CSS Class
.toppy {
:-webkit-full-screen {position: relative; top: -1310;}
:-moz-full-screen {position: relative; top: -1310;}
:-ms-fullscreen {position: relative; top: -1310;}
fullscreen {position: relative; top: -1310;}
}
JS Input
window.onscroll = function() {mss()};
function mss() {
var posi = document.body.scrollTop;
document.getElementById("toppy").style.top = -posi;
}
Depending on a position on a web page, this should give the value (posi). Negatived as CSS works on that way, and trying to update CSS with style(top) value (posi). However, no updating.
JS into which CSS influences
function FullScreen() { .... code .... }
CSS affects to this. If CSS has defined without class .toppy, function FullScreen works nicely opening full screen with the CSS's pre-set values (-1310) at the position downwards from the top.
But why is CSS's style property top not being updated by JS input function and therefore changing the position of the FullScreen to open at? My goal is to obtain the full screen to be opened at its current position on page. Some browsers do this automatically, some do not. Thus needing coding.
Or does one have to define a variable in css (e.g. var(--posi)) and proceed on this way but I do not have a real clue how to do that?
Many thanks for replies!
Update:
Thanks for the points. Valid ones. However, as the problem remains, I think the issue here is how to link a css to certain js being the case paricularry with this fullscreen. If I had two identical js fullscreen (expect function name), how would I define above kind of css to one js and another css to another js? As for me, it seems that css for fullscreen is (defined as above) not accepting any id or class tags, or I do not know how to link id to js? Syntaxing? Regards!

Hiding an element with hide() causes a page "jump"

I'm trying to create an effect where I display a big logo on page load. When the user scrolls pass the logo and navigation, I want to display a fixed nav bar with a smaller logo. I then want to hide the big logo so that when the user scrolls to the top they still see the fixed nav bar (i.e. the big logo and original navigation stay hidden).
However, when I remove a big block element with the .hide() property it causes the page to "jump" as the display:none property gets set. This reduces the usability of the page, as the location jumps the size of the element that was removed, potentially confusing users.
Is there a way I can get the effect I want, while still providing a smooth experience to the user? I've been thinking of potential options, but have been drawing blanks. Hoping you guys can inspire me :)
A simple JS fiddle can be seen here: http://jsfiddle.net/darudude/vA5WG/ (Note: You'll have to increase the result section to 720+px to get it to work properly - I'm still working on the responsive part)
The code in question:
function UpdateTableHeaders() {
var menu = $(".main_nav_menu"),
offset_top = menu.offset().top;
var scrollTop = $(window).scrollTop();
if (scrollTop > (offset_top + menu.height()))
{
$(".clone").addClass("floating_header");
$(".big_logo").hide();
}
}
$(window).scroll(function(){
UpdateTableHeaders();
});
You can try this ,
Add a new style
<style>
.hide {
position: absolute !important;
top: -9999px !important;
left: -9999px !important;
}
</style>
And change your JS to
$(".big_logo").addClass('hide');
Instead of
$(".big_logo").hide();
Use visibility:hidden then
$(".big_logo").css('visibility','hidden');
Maybe it is because a different browser - margin/padding thing. Have you tried to add this to the body element (or to the container element if it inherits some margins/paddings)
body{
margin:0;
padding:0;
width:100%;
}

How can this CSS card flip effect fall back gracefully when CSS3 support is lacking?

I'm using the library FlipClock.js to build an analog-style clock that uses a version of the CSS "card flip effect." Unfortunately, only after building out my project did I notice a long-standing bug affecting Internet Explorer 9 and below:
https://github.com/objectivehtml/FlipClock/issues/7
In IE9 and below, the clock time lags by one second (i.e., in the first second of animation, nothing visible changes), and the digits in the clock are also offset by a value of 1. My expectation is not for the CSS flip animation to work, but for the digits to change instantly as they currently do, only be correct.
I've been troubleshooting for a while but have yet to find a solution or even pinpoint the problem. I have a hunch that this isn't a script-related bug; I suspect that the digits are changing correctly in the HTML (hard to verify with IE's developer tools), but that they're just not showing as intended due to one or more CSS rules that were written not considering IE9's poor CSS3 support. I'm kind of expecting (or at least hoping) to stumble upon a CSS property or two that just fixes it.
The library is based on a proof-of-concept, which exhibits the same problem:
http://codepen.io/ademilter/pen/czIGo
I'm troubleshooting there to keep it simple, and if I find a fix, will submit a pull request to the FlipClock.js library.
I would greatly appreciate any help!
After removing the CSS animations and shadows, changing the z-index of li.before might do the trick (see http://codepen.io/cbuckley/pen/rysja):
body.play ul li.before {
z-index: 1; /* was previously 3 */
}
So you could use z-index: 1 by default, then feature-detect for CSS animations in the JavaScript and add a body class (say body.supports-animation). Then the relevant CSS might look like:
body.play ul li.before {
z-index: 1;
}
body.play.supports-animation ul li.before {
z-index: 3;
}
/* Prefix animation/background declarations with body.supports-animation too */
Caveat: I haven't tried this with FlipClock, nor have I actually tested on a browser without animation support, but I hope it gives one possible option :-)
Just changing the z-index will fix the problem for IE8 and IE9 but will break the transition for all modern browsers.
To Target specifically I8 or IE9 you can use this:
On your JS file add:
var doc = document.documentElement;
doc.setAttribute('data-useragent', navigator.userAgent);
then on your css you can detect IE8 and IE9 with this code (flipclock.css line 160):
/* PLAY */
.flip-clock-wrapper ul.play li.flip-clock-before {
z-index: 3;/*Original */
}
/*ie8 and ie9 fixes*/
html[data-useragent*='MSIE 8.0'] .flip-clock-wrapper ul.play li.flip-clock-before {
z-index: 1;
}
html[data-useragent*='MSIE 9.0'] .flip-clock-wrapper ul.play li.flip-clock-before {
z-index: 1;
}
That fixed the problem for me!

Interactive HTML webpage

EDIT: Thanks for a lot of great examples on how to solve these. I cant decide between who to accept yet, but I will go though all examples and see which I like the most. Great feedback guys! =D
I normally do these kind of things in flash, but this time it has to be compatible with mac, iPads and all those units too.
So, what do I need help with?
I've got a picture, with some "hotspots" on. I want to be able to click any of those hotspots to show some information.
This should be fairly basic and easy to achieve, but since I've never done this in html before I have to ask you guys =)
So, what would be the best way to do this? It have to be compatible with any browser and device, and it doesnt need to be very advanced. If it's possible to add effects to the box (sliding out, fading in, or anything like that) then thats a nice bonus, but not something I need.
Any help would be great!
BREAKDOWN:
I have a background image with some "hotspots" (numbers 1 and 2 in my example). The users should be able to either hover the mouse over any of these or click it to get more information, as seen in picture #2
This is that happens when you hover/click any of these hotspots.
Text and image is displayed inside a nice little info box.
If the user clicks "more information" it will open up even further to display more information if available. Like in this img:
I don't think the Javascript approach is really necessary here. I created a little CSS-only mock-up for you on JSBin.
Basically the point is that you enclose the image in a relatively positioned div, then absolute position the hotspots inside the same div. Inside the hotspots divs you will have the more info elements, showing only on :hover of their parents.
This makes it simple, and far more accessible.
Update: cropping the image equally from both sides
If you want to keep the image centered and still not use any javascript, you could set the required image as a background-image of the container, and setting its background-position parameters to center center.
You would have to make sure that the width of this div is set to the width of your image, and the max-width to 100%, so that when the window gets resized below the image width it stays at the center.
Now, a problem that I encountered here is how to make the hotspots stay center relatively to the image. I solved it this way:
I created a wrapper div for the hotspots with these characteristics:
margin: 0 auto;
position: relative;
width: 0px;
This basically makes sure that the wrapper div finds the center of our image. Then, you would position the hotspots relatively to the top-center position of the image, instead of the top-left as a starting point.
Then you have what you are looking for.
Working demo
Here's another approach, and in my opinion far superior to using a map or excessive JS. Place <div> elements on top of the element with the background-image and have HTML and CSS do the heavy lifting for you.
See it on JSFiddle
HTML
The HTML should seem pretty each enough to understand, we create <div>s with the class hotspot and rely on certain things being present. Namely .text (to show digit), .hover-popup (to show on hover) and .click-popup (which is inside .hover-popup and is shown when clicked).
<div id="hotspot1" class="hotspot">
<div class="text">1</div>
<div class="hover-popup">
I was hovered!
<div class="click-popup">
I was clicked on!
</div>
</div>
</div>
<div id="hotspot2" class="hotspot">
<div class="text">2</div>
<div class="hover-popup">
I was hovered!
<div class="click-popup">
I was clicked on!
</div>
</div>
</div>
CSS
This is where most of the magic happens, see the comments for further explanation.
/* These two position each hotspot */
#hotspot1 {
left:15%; /* we could use px or position right or bottom also */
top:20%;
}
#hotspot2 {
left:35%;
top:25%;
}
/* General styles on the hotspot */
.hotspot {
border-radius:50%;
width:40px;
height:40px;
line-height:40px;
text-align:center;
background-color:#CCC;
position:absolute;
}
.hotspot .text {
width:40px;
height:40px;
}
/* Show the pointer on hover to signify a click event */
.hotspot .text:hover {
cursor:pointer;
}
/* hide them by default and bring them to the front */
.hover-popup,
.click-popup {
display:none;
z-index:1;
}
/* show when clicked */
.hotspot.clicked .click-popup {
display:block;
}
/* show and position when clicked */
.hotspot:hover .hover-popup {
display:block;
position:absolute;
left:100%;
top:0;
width:300px;
background-color:#BBB;
border:1px solid #000;
}
JavaScript (with jQuery)
Unfortunately you're going to have to use some JavaScript for the clicking part as CSS doesn't have a 'clicked' state (outside of hacks with checkboxes). I'm using jQuery because it's dead easy to do what I want.
$(document).ready(function () {
$('.hotspot').click(function () {
$(this).toggleClass('clicked');
});
});
Creating the arrow
Over at css-tricks you can find a tutorial for attaching an arrow to a element using the :before and/or :after pseudo-elements. You can even 'simulate' a border around them by placing the :after element on top of the :before. But yea, lots of resources on how to do this.
You should be able to use the onclick or OnMouseOver event in the map area (define the href as "").
An example using OnMouseOver is here: http://www.omegagrafix.com/mouseover/mousimap.html
Give a class for that image in html (Ex: imgclass). And in javascript(using jquery), build that hover box in html format and bind it to 'mouseover' event of that image.
For example:
function bindhtmltoimage() {
myimg = $('body').find('.imgclass');
divSlot.each(function (index) {
$(this).bind('mouseover', function () {
try {
//position the hover box on image. you can customize the y and x axis to place it left or right.
var x = $(this).offset().left;
var y = $(this).offset().top;
var position = $(window).height() - ($("#divHover").height() + y);
var widthposition = $(window).width() - ($("#divHover").width() + x);
if (position < 0 || widthposition < 0) {
if (position < 0) {
$("#divHover").css({
position: 'absolute',
left: x + 20,
top: y - $("#divHover").height() - 20
});
}
if (widthposition < 0) {
$("#divHover").css({
position: 'absolute',
left: x - $("#divHover").width(),
top: y + 20
});
}
}
//build your html string for that hover box and apply to it.
$('#divHover').html("your Html content for that box goes here");
$('#divHover').show();
//if you want the box dynamically generated. create the html content and append to the dom.
}
catch (e) {
alert(e)
}
});
});
}
it will work fine in desktop and mobile. if you face any problem in touch devices, bind the function to click event instead of 'mouseover'.
Also, for map approach, i strongly recommend SVG instead of images.

Javascript Drop Down Menu over Image Rotator

Designer here, trying to code.
I am almost there! Trying to get a drop down menu from dynamic drive to work over an jQuery image rotator. Played with z-index. I can get the menu to work over the image rotation on all browsers except in IE compatibility mode, cannot click on the buttons in the rotator.
http://local495.bigrigmedia.com/
Any help would be greatly appreciated!
Always so much easier to get everything looking right in Photoshop eh? You can fix your overlap issue with 2 minor tweaks to the CSS:
styles.css
#top {
position: relative;
z-index: 2;
height: 155px;
}
ddsmoothmenu.css
.ddsmoothmenu{
position: relative;
z-index: 2;
/* remaining css */
}
homerotation.css
div#feature_list {
position: relative;
z-index: 1;
/* remaining css */
}
I also noticed you had a lot of z-index: -100 sprinkled around your CSS. Those are also going to cause you trouble. I would suggest taking them all out and just using the above 2 changes.
What the above 2 rules do is establish the stacking order for the menu and image rotator in a way that all browsers (including our friend IE) understands.
The trick with IE when using z-index is to make sure all the elements you're trying to overlap are in the same stacking context. IE creates a new stacking context whenever you use relative, absolute or fixed position on an element. In our case above, we're setting the stacking order on the top most elements in the stacking context (i.e. the document), therefore it will be respected.
Edit
Added a z-index to the #top container as this is actually the <div> that's at the same level in the document as <div id="feature_list">.

Categories

Resources