I am trying to determine the actual height of the browser in relationship to the screen height in jQuery. For some reason, the readings are far from accurate and I'd like to know why.
Basically the issue I'm having is that
The window.innerHeight and window.outerHeight are always exactly the same even though the tabs bar is being shown and there is an obvious (visual) difference between the 2...
Each of the readings above are always smaller than screen.height and screen.availHeight. I was under the impression that this should not be the case if the browser is maximized vs full screen vs sized vs minimized?
My requirement is to change the class of an element on the window.scroll event when that element reaches the top of the browser viewport. However, I am also mandated to change to a different class if the browser window is sized instead of maximized or full screen.
Here's the code that performs this operation however, like I mentioned above, the "maximized" if statement is never true... why?
function SetFloatingDivCheck(ContainerName, StartingClassName, FixedClassNameSized, FixedClassNameMaximized) {
$(document).ready(function () {
var ElemY = $('#' + ContainerName).offset().top - parseFloat($('#' + ContainerName).css('margin-top').replace(/auto/, 0));
$(window).scroll(function () {
var YPosition = $(window).scrollTop();
if (YPosition >= ElemY) {
$('#' + ContainerName).removeClass(StartingClassName);
//the following alert/debug shows this: 1050, 949, 949, 1010 when fired.
//alert("screen.height = " + screen.height.toString() + "\nwindow.innerHeight = " + window.innerHeight.toString() + "\nwindow.outerHeight = " + window.innerHeight.toString() + "\n screen.availHeight = " + screen.availHeight.toString());
if (screen.height == window.outerHeight || screen.availHeight == window.outerHeight)
{
$('#' + ContainerName).addClass(FixedClassNameMaximized);
}
else
{
$('#' + ContainerName).addClass(FixedClassNameSized);
}
}
else {
$('#' + ContainerName).removeClass(FixedClassNameSized);
$('#' + ContainerName).removeClass(FixedClassNameMaximized);
$('#' + ContainerName).addClass(StartingClassName);
}
});
});
}
Your testing is bugged. Your alert states window.outerHeight = " + window.innerHeight.toString()
Related
I've been trying to get a smooth scroll animation for a while now, but mainly in JS..
This hasn't been working out that well so I decided to try in CSS3.
Now I want to make this animation responsive by calling a JS function which adds the CSS rules for the animation responsive to the object the animation is for. Here is the JS code I've got so far. I'll also leave a Fiddle, but I'm new to that so things might not work right away.
function getTexts() {
var element = document.getElementsByClassName('toplink');
for (x = 0, len = element.length; x < len; x++){
var ID = element[x].textContent.toLowerCase();
var object = document.getElementById(ID);
console.log(object);
addCSSAnimator(ID);
}
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = document.getElementById(el);
var Class = DOM.getAttribute("class");
var Parent = DOM.parentElement.getAttribute("id");
var rect = DOM.getBoundingClientRect();
var rule = ".toplink[ id= '"+el+"' ]:target - #"+Parent+" div."+Class+" {\n" +
"-webkit-transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"}";
console.log("Stylesheet: ",sheet," object: ",DOM," Class: ",Class," offset X&Y:",rect.x," ",rect.y);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
https://jsfiddle.net/dtj46c64/
You may try moving to jquery for this solution. Use document.ready and window.resize functions to handle the animation and also instead of for loop. use the jquery .each() function to get the elements. Try working around the following code i changed for you to go along with. Hope this puts you in the right direction to achieve your goal:
<script>
function getTexts() {
$(".toplink").each(function () {
let ID = $(this)
console.log(ID);
addCSSAnimator(ID);
});
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = el;
var Class = DOM.attr("class");
var Parent = DOM.parent().attr("id");
var rect = DOM[0].getBoundingClientRect();
var rule = ".toplink[ id= '" + el + "' ]:target - #" + Parent + " div." + Class + " {\n" +
"-webkit-transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"}";
console.log("Stylesheet: ", sheet, " object: ", DOM, " Class: ", Class, " offset X&Y:", rect.left, " ", rect.top);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
$(window).on('resize', function () {
getTexts();
});
$(document).ready(function () {
getTexts();
});
</script>
Notice i changed the rect.y to rect.top as on some browsers the getBoundingClientRect fucntion does not return x and y values but left and top are always filled.
Also dont know why you are getting id of the parent of the object as there is no id set to the parent of the anchor class="toplink" so it will always return as null or empty.
Sorry for not a 100% answer as got busy but i hope the solution so far i suggested will help you tweak and find what your looking for.
I've built a custom, dirt and quick, jQuery/JavaScript slider... which works great, except for one issue.
When using the 'Previous' button, it works perfectly the first time you click it, but then when you click it again, the length of the array becomes '2' when it should be '1' because there are only two results...
Code:
jQuery("#sliderNext").click(function(event) {
$("#sliderNext").fadeOut(50);
$("#sliderPrevious").fadeOut(50);
setTimeout(function() {
$("#sliderNext").fadeIn(100);
$("#sliderPrevious").fadeIn(100);
}, 900);
slideNumber++;
if(slideNumber < image.length && caption.length) {
jQuery(".slider-image").css("background-image", "url(" + image[slideNumber] + ")");
jQuery("#caption").text(caption[slideNumber]);
console.log("if: " + slideNumber);
}
else
{
slideNumber = 0;
jQuery(".slider-image").css("background-image", "url(" + image[slideNumber] + ")");
jQuery("#caption").text(caption[slideNumber]);
console.log("else: " + slideNumber);
}
});
jQuery("#sliderPrevious").click(function(event) {
$("#sliderNext").fadeOut(50);
$("#sliderPrevious").fadeOut(50);
setTimeout(function() {
$("#sliderNext").fadeIn(100);
$("#sliderPrevious").fadeIn(100);
}, 900);
slideNumber--;
console.log(image.length);
if(slideNumber >= 0 && slideNumber <= image.length) {
jQuery(".slider-image").css("background-image", "url(" + image[slideNumber] + ")");
jQuery("#caption").text(caption[slideNumber]);
console.log("if: " + slideNumber);
}
else
{
slideNumber = image.length;
jQuery(".slider-image").css("background-image", "url(" + image[slideNumber] + ")");
jQuery("#caption").text(caption[slideNumber]);
console.log("else: " + slideNumber);
console.log(image.length);
}
});
I've tried using different operators, if/else statements, it always sets it to 2 on the second click.
Could anybody point me in the right direction for why it would do this?
This might be because your click event gets bound the second time to the button and therefore jumps twice.
Try to "unbind" your click events before binding them.
$("#sliderPrevious").unbind();
// and then
jQuery("#sliderPrevious").click(function(event) {...});
Do this to every event that gets bound when intializing the page.
EDIT
var myArray = [a,b];
Note that myArray.length == 2 but myArray[2] is undefined.
Array indexes start at [0] thats why you have to substract 1 from your "counter" variable.
I have a javascript function that opens a login.htm window in the mode I would like after I click a button on my index.htm page ....
function openApp() {
var options = "channelmode=" + 1 +
",resizable=" + 1 +
",menubar=" + 0 +
",toolbar=" + 0 +
",location=" + 0 +
",titlebar=" + 1 +
",status=" + 1 +
",scrollbars=" + 1;
var name = "reporting";
var appURL = "login.htm"
var newWindow = window.open(appURL,name,options);
newWindow.focus();
}
It works fine but now I would like to move the functionality of opening the window into the login.htm window on load function.
For example if someone goes to login.htm itself, i want the window to open up in that mode.
I've tried a few things but can't figure this out. Can someone please help me.
I am using jquery so I could do it using jquery.
thanks
If you've got a DOM element with a click event that opens the login.htm and you want to open a new window as well with the same window properties if another DOM element is clicked just set the click event to that that DOM element, as in <span onclick="openApp()">Login</span>.
You could navigate to the log in page and set a setTimeout.
Just place this code in the log in page that the user navigates to, and it will open a new window on its own after the log in page DOM is loaded.
<script type="text/javascript">
setTimeout(function () {
var openApp = function () {
var options = "channelmode=" + 1 +
",resizable=" + 1 +
",menubar=" + 0 +
",toolbar=" + 0 +
",location=" + 0 +
",titlebar=" + 1 +
",status=" + 1 +
",scrollbars=" + 1;
var name = "reporting",
appURL = "login.htm",
newWindow = window.open(appURL, name, options);
newWindow.focus();
}();
}, 100);
</script>
You would take the section that var options is being set and put it outside of the openApp() function, like so:
var options = "channelmode=" + 1 +
",resizable=" + 1 +
",menubar=" + 0 +
",toolbar=" + 0 +
",location=" + 0 +
",titlebar=" + 1 +
",status=" + 1 +
",scrollbars=" + 1;
function openApp() {
var name = "reporting";
var appURL = "login.htm"
var newWindow = window.open(appURL,name,options);
newWindow.focus();
}
Then you can call openApp() however you'd like.
If you want to run openApp() to execute when the whole page is fully loaded (i.e. all images are loaded) then you'd do the following:
$(window).load(function(){
openApp();
});
If you want to execute openApp() when the document is in its "ready" state (when he DOM is available to manipulate), then do the following:
$("document").ready(function(){
openApp();
});
I have to load a very big JSON object and perform various expensive processes. For this reason, I am showing a progress bar which increments a total of five times. If I have to load 10000 items, it will update every 2000 times, etc.
The problem is the effect is not visible because all the stack executes after the entire function is complete, instead of updating the progressbar at every 20% of the process. It doesn't matter if I try to load 10000 items or 2 million items, same stuff happens, and judging by the computation delay between console logs, there is definitely enough processing time to show a visible progress effect. Perhaps I'm not understanding the javascript for(I know this wasn't the way to do it). How do you track an expensive process and make a visible progress bar effect properly?
This is the js file.
login with
username : admin
password: testit
var initItems = function(publicationItems) {
var publications = new Array();
var numberOfItems = goog.object.getCount(publicationItems);
var minStep = 20;
var currentProgress = 20;
var progressBarStep = parseInt(numberOfItems / 5);
var i = 0;
goog.object.forEach(publicationItems, function() {
var currentName = publicationItems.name;
var currentCat = publicationItems.categories;
// Insert clear div to break line after every 5 items.
if (i % 5 == 0 && i != 0)
publications.push(this.clear);
if(i % progressBarStep == 0)
{
progressBar.setValue(currentProgress);
console.log(i + ' ' + progressBarStep + ' ' + currentProgress + ' ' + progressBar.getValue());
currentProgress += minStep;
}
i++;
publications.push(goog.dom.createDom('div', {
'style' : 'width:' + this.currentPublicationDimension + 'px;height:' +
this.currentPublicationDimension + 'px;border:1px solid #B3B3B3;' +
'float: left;margin-top: 5px;background-color: #FCFCFC;' +
'max-width:' + this.currentPublicationDimension + 'px;max-height:' +
this.currentPublicationDimension + 'px;_height:' +
this.currentPublicationDimension +
'px;_width:' + this.currentPublicationDimension + 'px;margin-left:' +
this.publicationLeftMargin + 'px;',
'class' : 'publication'
}, currentName, currentCat));
}, this);
return publications;
};
And the context from where this function was called:
// Bind COMPLETE event listener to ajaxHandler.
goog.events.listen(ajaxHandler, goog.net.EventType.SUCCESS,
goog.bind(function(e) {
//goog.style.showElement(progressBarContainer, false);
goog.dom.append(this.mainViewPublications, initItems.call(this, e.target.getResponseJson()));
}, this), false, this);
The problem is that JavaScript is Singlethreaded and first tries to execute the calculations. The ProgressBar is asynchronous and will only update, if the thread is not busy.
You could use callbacks like following
function a () {
/* do one iteration */
progressBar.setValue(currentProgress);
goog.Timer.callOnce(a, 10);
}
The Problem with that, is that you can't pass parameters to the function and you have to use global variables (or at least 'object' wide variables).
I currently have the same issue and haven't found a really good solution. So this is a first approach. If I find another solution I will update it here.
I can't figure out why this script isn't working in IE7 and 8. It works fine in all other browsers, but for some reason, in IE7 and 8 this script is only firing the // thumbs hover bit, and not the // loading images bit (which is actually more important). Everything seems to be fine, does anyone have any ideas?
function featuredJS() {
$("[title]").attr("title", function(i, title) {
$(this).data("title", title).removeAttr("title");
});
// loading images
var last = "featured/01.jpg";
$("#thumbs a").click(function(event) {
event.preventDefault();
var position = $(this).attr("class");
var graphic = $(this).attr("href");
var title = $(this).attr("alt");
var description = $(this).data("title");
var currentMargin = $("#full-wrapper #full").css("marginLeft");
var currentWidth = $("#full-wrapper #full").css("width");
var transitionTest = currentMargin.replace("px", "") * 1;
if(last != graphic && ((transitionTest % 938) == 0 || transitionTest == 0)) {
$("#placeholder").before( "<div class='featured'><div class='description " + position + "'>" + "<h3>" + title + "</h3>" + "<p>" + description + "</p>" + "</div><img src=\"" + graphic + "\" /><div style='clear:both;'></div></div>" );
$("#full-wrapper #full").animate({
marginLeft: "-=938px"
}, 500);
$("#full-wrapper #full").css("width","+=938px");
last = graphic;
};
});
// thumbs hover
$("#thumbs .thumb").hover(
function () {
$(this).find(".red-bar").animate({height:"72px"},{queue:false,duration:500});
},
function () {
$(this).find(".red-bar").animate({height:"3px"},{queue:false,duration:500});
}
);
};
Demo page at http://www.weblinxinc.com/beta/welex/demo/
Your problem is caused by not having a margin set to begin with. transitionTest then becomes NaN because the style is auto, not 0px like you're expecting. Consider trying this instead:
var transitionTest = parseInt("0"+currentMargin,10);
This will trim off the "px" for you, as well as handle the case where the margin is a keyword.