I'm fetching some line charts using Google's Chart API and placing it in a DIV like this:
<div class="chart" style="display:block">
<img src="http://chart.apis.google.com/chart?chs=620x40&cht=lfi&chco=0077CC&&chm=B,E6F2FA,0,0,0&chls=1,0,0&chd=t:27,25,25,25,25,27,100,31,25,36,25,25,39,25,31,25,25,25,26,26,25,25,28,25,25,100,28,27,31,25,27,27,29,25,27,26,26,25,26,26,35,33,34,25,26,25,36,25,26,37,33,33,37,37,39,25,25,25,25">
</div>
I have to pass the height and width of the chart image required and the Google Chart API renders it e.g. chs=620x40. I'd like the chart image to be the with of my parent div. I need to calculate the width and dynamically construct this chart URL so that I get a chart image of the right size. How can I do this?
(I'm not too bright with jQuery and I'm trying to avoid using some bloated libraries)
Thanks
You can use the following JavaScript (with jQuery):
function sizeCharts(){
$(".chart").each(function(){
var w = $(this).width();
var h = $(this).height(); // or just change this to var h = 40
$("<img>").attr("src","http://chart.apis.google.com/chart?chs=" + \
escape(w) + "x" + escape(h) + "&[etc]").appendTo(this);
});
}
$(function(){
sizeCharts();
var shouldResize = true;
$(window).bind("resize",function(){
if(!shouldResize){
return;
}
shouldResize = false;
setTimeout(function(){
sizeCharts();
shouldResize = true;
},1000);
});
});
Replace [etc] with the rest of the url you wish to use. What happens in the above code is it will iterate through everything with the chart class in your page and puts the chart into it with the appropriate size.
If you use a liquid layout (i.e. your site resizes to fill a certain percentage of the screen), then you will also want to include the $(function(){ ... }) bit, which runs the same code when the page is resized. Note the use of timers here, otherwise the same chart will be reloaded for every pixel that the window is resized.
Related
I'm trying to detect the position of the browser's scrollbar with JavaScript to decide where in the page the current view is.
My guess is that I have to detect where the thumb on the track is, and then the height of the thumb as a percentage of the total height of the track. Am I over-complicating it, or does JavaScript offer an easier solution than that? What would some code look like?
You can use element.scrollTop and element.scrollLeft to get the vertical and horizontal offset, respectively, that has been scrolled. element can be document.body if you care about the whole page. You can compare it to element.offsetHeight and element.offsetWidth (again, element may be the body) if you need percentages.
I did this for a <div> on Chrome.
element.scrollTop - is the pixels hidden in top due to the scroll. With no scroll its value is 0.
element.scrollHeight - is the pixels of the whole div.
element.clientHeight - is the pixels that you see in your browser.
var a = element.scrollTop;
will be the position.
var b = element.scrollHeight - element.clientHeight;
will be the maximum value for scrollTop.
var c = a / b;
will be the percent of scroll [from 0 to 1].
document.getScroll = function() {
if (window.pageYOffset != undefined) {
return [pageXOffset, pageYOffset];
} else {
var sx, sy, d = document,
r = d.documentElement,
b = d.body;
sx = r.scrollLeft || b.scrollLeft || 0;
sy = r.scrollTop || b.scrollTop || 0;
return [sx, sy];
}
}
returns an array with two integers- [scrollLeft, scrollTop]
It's like this :)
window.addEventListener("scroll", (event) => {
let scroll = this.scrollY;
console.log(scroll)
});
Answer for 2018:
The best way to do things like that is to use the Intersection Observer API.
The Intersection Observer API provides a way to asynchronously observe
changes in the intersection of a target element with an ancestor
element or with a top-level document's viewport.
Historically, detecting visibility of an element, or the relative
visibility of two elements in relation to each other, has been a
difficult task for which solutions have been unreliable and prone to
causing the browser and the sites the user is accessing to become
sluggish. Unfortunately, as the web has matured, the need for this
kind of information has grown. Intersection information is needed for
many reasons, such as:
Lazy-loading of images or other content as a page is scrolled.
Implementing "infinite scrolling" web sites, where more and more content is loaded and rendered as you scroll, so that the user doesn't
have to flip through pages.
Reporting of visibility of advertisements in order to calculate ad revenues.
Deciding whether or not to perform tasks or animation processes based on whether or not the user will see the result.
Implementing intersection detection in the past involved event
handlers and loops calling methods like
Element.getBoundingClientRect() to build up the needed information for
every element affected. Since all this code runs on the main thread,
even one of these can cause performance problems. When a site is
loaded with these tests, things can get downright ugly.
See the following code example:
var options = {
root: document.querySelector('#scrollArea'),
rootMargin: '0px',
threshold: 1.0
}
var observer = new IntersectionObserver(callback, options);
var target = document.querySelector('#listItem');
observer.observe(target);
Most modern browsers support the IntersectionObserver, but you should use the polyfill for backward-compatibility.
If you care for the whole page, you can use this:
document.body.getBoundingClientRect().top
Snippets
The read-only scrollY property of the Window interface returns the
number of pixels that the document is currently scrolled vertically.
window.addEventListener('scroll', function(){console.log(this.scrollY)})
html{height:5000px}
Shorter version using anonymous arrow function (ES6) and avoiding the use of this
window.addEventListener('scroll', () => console.log(scrollY))
html{height:5000px}
Here is the other way to get the scroll position:
const getScrollPosition = (el = window) => ({
x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});
If you are using jQuery there is a perfect function for you: .scrollTop()
doc here -> http://api.jquery.com/scrollTop/
note: you can use this function to retrieve OR set the position.
see also: http://api.jquery.com/?s=scroll
I think the following function can help to have scroll coordinate values:
const getScrollCoordinate = (el = window) => ({
x: el.pageXOffset || el.scrollLeft,
y: el.pageYOffset || el.scrollTop,
});
I got this idea from this answer with a little change.
I am trying to place markers on points of interest (poi) on an Image.
These poi have been set in a different software and were stored in a database. The position is determined by their pixel position relative to the original Image. In my webapp the Images are scaled down thanks to panzoom.js (a plugin irrelevant to my question I think). I got the right formula to scale the markerposition, the only Problem is:
In firefox I'm unable to read the Images size in time (In Chrome that's not an Issue).
This is the Code
$(document).ready(function ()
{
var imagectrl = document.getElementById('<%= img.ClientID %>');
var hiddenfield = document.getElementById('<%= hf.ClientID %>');
if (hiddenfield.value == "")
{
var myWidth;
var myHeight;
myWidth = imagectrl.clientWidth;
myHeight = imagectrl.clientHeight;
hiddenfield.value = myWidth + ';' + myHeight;
__doPostBack();
}
});
If I do a postback manually (clicking a button that shows the Image in higher quality) the size gets written correctly.
I've also tried calling an identical function from Code behind when my X or Y are 0, but nothing worked.
What can i do to get the Images size when first loading the page?
Firefox has a different implementation on asynchronous operations like image loading than Chrome. I guess this could be the reason why in Chrome you can access the image right away with $(document).ready, but in Firefox the image source gets loaded after the document is ready - thus clientWidth and clientHeight will be undefined.
Solution: Define an onload event handler on your image and put your logic into that method:
$(document).ready(function ()
{
var imagectrl = document.getElementById('<%= img.ClientID %>');
var hiddenfield = document.getElementById('<%= hf.ClientID %>');
imagectrl.onload = function() {
if (hiddenfield.value == "")
{
var myWidth;
var myHeight;
myWidth = imagectrl.clientWidth;
myHeight = imagectrl.clientHeight;
hiddenfield.value = myWidth + ';' + myHeight;
__doPostBack();
}
}
});
I found a Solution:
No matter what I did, the Image itself can't be measured in time.
So i gave the Image the height of it's surrounding control via CSS and used
AddHandler dvGalerieFill.Load, AddressOf Me.measure_height
in the Page_Load method to react to the loading of the surrounding control.
In "measure_height" I called my Javascript function.
Through the height of the control (wich is the height of my image)
I can calculate the width of my image as height and width rescale with the same factor.
I have an iFrame in my jsp page where in page load it should have height and width as 600 and 400 respectively. This iFrame contains some page having some forms in it, once the form is filled and submitted, it will redirected to a thank you page. At that time I need the height of the iFrame as 200(because the page contents are less and I need to reduce the white space in it). how to achieve this? I get n number of links in stack exchange itself but nothing is useful in this case.
Is there any way to check if the iFrame src url is changed? If so I can make a condition and do the below code to reduce the height.
<script type="text/javascript">
function iframeLoaded() {
var iFrameID = document.getElementById('idIframe');
if(iFrameID) {
iFrameID.height = "200";
iFrameID.width = "400";
iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
iFrameID.width = iFrameID.contentWindow.document.body.scrollHeight + "px";
}
}
</script>
The above function is working fine if i give it in iFrame page load but I need to set this only when I get the thank you page inside iFrame.
Request to kindly help on this.
you can use something like cookie.js (https://github.com/js-cookie/js-cookie) for creating a helper cookie for each step in your iframe.
(function($) {
$( '#submit-button').on( "click", function() {
Cookies.set('isSubmitted', true);
});
})(jQuery);
Now you can check if the cookie is set and resize the iframe
(function($) {
if(Cookies.get('isSubmitted') === true) {
$('#iFrameID').height(200);
}
})(jQuery);
After this you can delete this cookie
Cookies.remove('isSubmitted');
You can do iFrame url change check in the parent page like this:
function check(){
$('#idIframe').load(function() {
console.log("the iframe has changed");
});
};
$("#idIframe").on("mouseenter",function(){
window.setInterval(check, 100); // 100 ms
});
I'm trying to implement dragging an item onto a jquery slider. For example, if the item is dropped onto 86% of the slider I would like to POST this position to the server so the item can be place 86% along the result set on the server.
How do you detect dropping onto a jQuery slider and the percentage POSTed to the server?
Since I'm not so good at explaining things, I made a jsFiddle for you. Although this might not be exactly what your looking for, it should be a good starting point!
Here's the code :
$(function () {
//the draggable object
$("#dragobject").draggable();
//Prepare the slider
var range = 100,
sliderDiv = $("#slider");
// Activate the UI slider
sliderDiv.slider({
min: 0,
max: range,
create : function(){
$(this).find(".ui-slider-handle").hide();
}
});
// Number of tick marks on slider
var position = sliderDiv.position(),
sliderWidth = sliderDiv.width(),
minX = position.left,
maxX = minX + sliderWidth,
tickSize = sliderWidth / range;
//Set slider as droppable
sliderDiv.droppable({
//on drop
drop: function (e, ui) {
var finalMidPosition = $(ui.draggable).position().left + Math.round($("#dragobject").width() / 2);
//If within the slider's width, follow it along
if (finalMidPosition >= minX && finalMidPosition <= maxX) {
var val = Math.round((finalMidPosition - minX) / tickSize);
sliderDiv.slider("value", val);
alert(val + "%");
//do ajax update here to set the position
/*$.ajax({
type: "POST",
url: url,
data: val,
success: function () {
//congrats
},
dataType: dataType
});*/
}
}
});
});
And here's the jsFiddle link : jsFiddle example
Hope it helps,
Marc.
SOURCES :
Jquery slider that slides while mouse move,
jQuery UI slider
Since you are using jQuery, lets assume you are using jQuery UI for your drag and drop. First read this: http://api.jqueryui.com/droppable/#event-drop
Then realize that you get the offset position of the dropped element relative to the droppable container as part of the event. This would be where you could compute that into percentage if you needed.
For example, dropped at position left -> 90px of a container that you know to be 100px wide means 90% is your magic number.
Or if you are using native drag and drop, check out this simple edit: http://jsbin.com/ezuke/3283/edit . If you pop a console log on the event in the drop event, you will see that it also exposes the offset of where you dropped it and you could again consume that in your calculation of %.
Google Image Search returns Images of different sizes. even their Thumbs are of different size. But still they are arranged in such a way that keeps a clean margin. even resizing the browser keeps the left and right alignment proper. What I've noticed is they group a Page of Image into an ul and each image is in an li. not all rows contain same amount of images. But still how they manage to keep images of different sizes properly aligned ?
EDIT
Though I've accepted an answer Its not exact match. It may be a near match. However I still want to know What is the exact procedure they are doing. I cannot chalk out the pattern.
It seems that they wrap a page in a <ol> and put images in <li> But when I resize the images are redistributed among pages. But how many images the page <ol> should contain now is to be decided. What procedure can be used to accomplish that ? and also images are resized based on a standard height I think. and that standard height is changed on resize. How how much ? how that is decided ?
It's not exactly the same thing, but you might get some useful ideas about how to optimize image "packing" by looking at the approach taken by the jQuery Masonry plug-in.
They know how big each thumbnail is, since it's stored in their image database. They just make each <li> float left, and make them a fixed size based on whatever the largest image is within that section of images.
I've written a little plugin just to do that HERE you can watch it in action:
(function($){
//to arrange elements like google image
//start of the plugin
var tm=TweenMax;
var positionFunc= function(options, elem){
var setting=$.extend({
height:150,
container:$('body'),
margin:5,
borderWidth:1,
borderColor:'#000',
borderStyle:'solid',
boxShadow:'0 0 0 #000',
borderRadius:0,
type:'img'
},options);
tm.set($(elem),{
'max-height':setting.height
});
$(elem).wrap('<div class="easyPositionWrap"></div>');
var winsize=setting.container.width();
var thisrow=0;
var elementsused=0;
var row=0;
tm.set($('.easyPositionWrap'),{
border:setting.borderWidth+'px '+setting.borderStyle+' '+setting.borderColor,
borderRadius:setting.borderRadius,
boxShadow:setting.boxShadow,
margin:setting.margin,
height:setting.height,
position:'relative',
display:'block',
overflow:'hidden',
float:'left'
});
$('.easyPositionWrap').each(function(index, element) {
if(thisrow<winsize){
thisrow+=$(this).width()+(setting.margin*2)+(setting.borderWidth*2);
}
else{
var currentwidth=thisrow-$(this).prevUntil('.easyPositionWrap:eq('+(elementsused-1)+')').width()-(setting.margin*2)+(setting.borderWidth*2);
var nextimagewidth=$(this).prev('.easyPositionWrap').width()+(setting.margin*2)+(setting.borderWidth*2);
var elems=$(this).prevAll('.easyPositionWrap').length-elementsused;
var widthtobetaken=(nextimagewidth-(winsize-currentwidth))/(elems);
if(widthtobetaken!=0){
if(elementsused==0){
$(this).prevUntil('.easyPositionWrap:eq(0)').each(function(index, element) {
$(this).width($(this).width()-widthtobetaken);
$(this).find(setting.type+':first-child').css('margin-left','-'+(widthtobetaken/2)+'px');
});
$('.easyPositionWrap:eq(0)').width($('.easyPositionWrap:eq(0)').width()-widthtobetaken);
$('.easyPositionWrap:eq(0) '+setting.type).css('margin-left','-'+(widthtobetaken/2)+'px');
}
else{
$(this).prevUntil('.easyPositionWrap:eq('+(elementsused-1)+')').each(function(index, element) {
$(this).width($(this).width()-widthtobetaken);
$(this).find(setting.type+':first-child').css('margin-left','-'+(widthtobetaken/2)+'px');
});
}
}
elementsused+=elems;
thisrow=$(this).width()+(setting.margin*2)+(setting.borderWidth*2);
}
});
$(window).resize(function(){
clearTimeout(window.thePositionTO);
window.thePositionTO=setTimeout(function(){
$(elem).each(function(index, element) {
$(this).unwrap('.easyPositionWrap');
$(this).data('easyPositioned',false);
});
$(elem).easyPosition(options);
},200);
});
}
$.fn.easyPosition= function(options){
if($(this).data('easyPositioned')) return;
positionFunc(options, this);
$(this).data('easyPositioned',true);
};
//end of the plugin
}(jQuery));
$(window).load(function(){
$('img').easyPosition();
});
libraries to include:
jQuery
GreenSock's TweenMax