I am trying to create/invent a new javascript slider object which will work by displaying a base line image:
http://imgur.com/DuVkE.png
then I want to use these 'knobs' to layer on top depending on certain circumstances
http://imgur.com/GKkqx.png
These have already been 'cut up' and will be placed on one of the three black knobs. I have many different colors because I plan to run through them so that the color appears to transform from one, to the other.
So I need to be able to attach an image to the id I received from the user and then manipulate the image later.
My code:
<div id='option1'></div>
<script type="text/javascript">
var slide1 = new slider("option1");
My constructor will look something like this:
function slider(id) {
var obj = document.getElementById(id);
if (!obj) {
var state = -1;
return -1;
}
var state = 0; //blank state
//alert("in");
//alert(document.getElementById(id).className);
//this.addClass("hSliderBack"); INCORRECT SYNTAX!!!
$("#"+id).addClass("hSliderBack"); //this works
}
I fixed the problem with the addClass above, though a little ugly.
My CSS script:
.hSliderBack
{
background-image: url('/Switches/switchLine.png');
background-repeat: no-repeat;
padding-left: 2px; /* width of the image plus a little extra padding */
display: block; /* may not need this, but I've found I do */
}
This is how I can add a picture to my constructor. Still a lot of work to do, but at least it's a start. Any comments are still appreciated as I am very green!!
What you write here:
//obj.innerHTML = "<img src=' this doesn't seem right to me.
is in fact one perfectly reasonable and viable way. You enter into the DOM the <img> node referencing the image you want to display.
However, more common and perhaps more maintainable solution in many cases is to have a CSS style that references a background image, and you enter a <div> into the DOM using the style that causes your image to be displayed.
You should ask yourself, though, is it best to do this without any support from tools. Many of the most popular JavaScript libraries have tools like this built in, or at the very least, have methods that make building this type of code much, much easier.
Of course, if you are doing this to learn the basics of web development before using a framework so you understand what they are doing more thoroughly, more power to you :-)
Related
I am writing an Ember.js web-application, designed to be the user interface of an automation system, that polls data from the LAN server every two seconds in order to have on display always the "live" process data.
This application is accessible from a wirless hotspot, to allow registered users to browse it, so potentially any device (tablets, smartphones, laptops...) could be the actual client.
On some pages, there are icons that change according to some conditions, and to implement this effect I declared several img tags, and I make the ones I dont need invisible by styling it with CSS display: none.
In HTML:
<img class="icon-active" src="/images/icon1.jpg" />
<img class="icon-inactive" src="/images/icon2.jpg" />
In Javascript, every two seconds:
var visibleElement = null;
var invisibleElement = null;
if( this.get("whatever").active == true )
{
visibleElement = this.element.getElementsByClassName("icon-active")[0];
invisibleElement = this.element.getElementsByClassName("icon-inactive")[0];
}
else
{
visibleElement = this.element.getElementsByClassName("icon-inactive")[0];
invisibleElement = this.element.getElementsByClassName("icon-active")[0];
}
visibleElement.style.display = null;
invisibleElement.style.display = "none";
Everything works fine, on laptops and tablets, but on some smarthphones, the images are loaded every time I set visibleElement.style.display = null;, it means, every two seconds, the visible icon is GETted again and again from server.
I dont want it to happen at first to reduce data traffic, that is not a problem at all, but I don't like fetching resources even if not required, second, the image reload generates an annoying flicker effect, that is really unlookable.
How can I force every client to cache images as tablets and laptops do?
----- more info -----
Thanks everyone for your support! Here you have some news:
I tried as suggested to comment-out all the javascript code that works on style.display and modify the HTML (template) as follows:
{{#if whatever.active}}
<img class="icon-active" src="/images/icon1.jpg" />
{{else}}
<img class="icon-inactive" src="/images/icon2.jpg" />
{{/if}}
and I got the same result. So I tried to roll back the HTML and leave the javascript commented, in such way I should have always all the icons visible, and surprise... they are all flickering and being requested every two seconds...
I guess the issue is due to the fact that some (maybe not up-to-date?) smartphone browsers are redrawing completely the images as the ember-views bound data gets updated. I will investigate more on which browser/version has this problem and make sure all of the testing devices use the last version of their browsers - since ember uses the latest javascript features, better cut-out old fashioned clients.
The code used to refresh data every two seconds follows, please notify if you see anything uncommon:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
// record generation code here...
},
afterModel()
{
Ember.run.later(this, function()
{
this.refresh();
}
, 2000);
}
});
----- solution -----
With new up-to-date browsers is not happening, so, this behavior exists only "in the past"... For sake of completeness I should find a solution to make it work properly also on "old" browsers, but I don't have time to spend on this.
If anyone of you figures out a 360 degrees solution an answer is still appreciated.
As I see those icons are static. So my suggestion is to use css:
1) Use spans(or divs) instead if images
2) Add icon as background image
html:
<p><span>active parameter</span><span class="icon active"></span></p>
<p><span>inactive parameter</span><span class="icon inactive"></span></p>
css:
.item
width: 16px //icon dimensions
height: 16px
// you may also add display: inline same as for images and so on
.active
background-image: url('/images/icon1.jpg')
.inactive
background-image: url('/images/icon2.jpg')
Benefit: Images will be loaded once by css engine along with styles.
PS: You can get rid of inactive class if your icon is inactive by default:
html:
<p><span>active parameter</span><span class="icon active"></span></p>
<p><span>inactive parameter</span><span class="icon"></span></p>
css:
.item
width: 16px //icon dimensions
height: 16px
background-image: url('/images/icon2.jpg')
// you may also add display: inline same as for images and so on
.active
background-image: url('/images/icon1.jpg')
PPS: It's really easy to manage classes with Ember by using classNameBindings
You need to set the image display to none.
Set the display to either inline-block or block for visible and none for not visible.
Preferably use css classes, since you are doing it with javascript. It might delay the action of hiding the images while the page loads.
You can use css classes like
.active{
display:block;
}
.inactive{
display:none;
}
Use these classes to add or toggle for a specific img element.
Still there will requests to server for images because you are only hiding the images through styles.
Display MDN
I am calling the following function and passing it the location of an image:
function show_image(source) {
var img = d3.select("#right-section").append("img").attr("src",source)
img.transition().duration(5000).easeLinear;
}
Here is the function that uses some JQuery to empty the relevant HTML div object (right-section) and then show the image:
function Con1aaRight(div) {
$("#right-section").empty();
show_image("images/netflix.jpg");
}
The problem is the image is showing but not fading in like I would like it to (with d3.ease in the show_image function). I probably should be using JQuery but I would like to incorporate d3. Similar transition/animation ideas welcome. I am building a scrolling webpage tutorial on a data science topic with text on the left and images on the right.
The problem here is understanding what is a D3 transition and how it works.
A D3 transition, as the name implies, transitions from one state, or value, to another state.
That being said, you can, for example, transition...
A position: from x = 10 to x = 60.
A color: from green to blue.
A font size: from 10px to 18px.
An opacity: from 0.2 to 0.9.
A stroke width: from 1px to 5px.
... and several other attributes/styles.
However, you cannot transition this:
non-existence ➔ existence
As Bostock, creator of D3, once said (emphasis mine):
When modifying the DOM, use selections for any changes that cannot be interpolated; only use transitions for animation. For example, it is impossible to interpolate the creation of an element: it either exists or it doesn’t. (source)
Solution: transition the opacity of the image:
var body = d3.select("body");
show_image("http://www.defenders.org/sites/default/files/styles/large/public/tiger-dirk-freder-isp.jpg")
function show_image(source) {
var img = body.append("img").attr("src", source).style("opacity", 0)
img.transition().duration(5000).ease(d3.easeLinear).style("opacity", 1)
}
<script src="https://d3js.org/d3.v4.min.js"></script>
PS: get rid of that jQuery code. You don't need jQuery when using D3. Mixing jQuery and D3 is not only unnecessary but also, in some cases, it will make things silently break.
I was thinking about how to make some cool image effects in browser, and I know it may be a little late to be heading down this train of thought with HTML5/CSS3 up and coming, but I was wondering what the inherent limitations / problem points there would be with implementing a library that essentially created divs each to hold a pixel of an image using background offsets. It is clear that this will create many divs, but if you wanted to work with only rows or columns on a small image it doesn't seem like this would be that unreasonable. With browser caching images, a request wouldn't have to be made for every segment, and the only other potential problem I can see is the processing of the positioning, which I imagine won't be a problem. I don't really have anything at this point to stop from going forward playing with images like this (so I will!), but I'm curious if there is anything that I am overlooking here that would make the idea unfeasible, and especially anything tricky I should be aware of. Thanks :)
Edit: Tried this, and it seems like there is either an inherent problem or a problem in my code (sorry it sucks, was just playing around), use with any image and you will see the difference.
var lpath = "images/logo.png"
window.onload = function(){
console.log('test');
$('body').append("<img id='logo' style='display:none' src="+lpath+">");
console.log($('#logo').width());
console.log('hello');
var logod = $('<div></div>')
.addClass('i')
.width($('#logo').width())
.height($('#logo').height())
.css('background-image','url('+lpath+')')
$('body').append(logod);
for(var i = 1; i <= $('#logo').height(); i++){
var cons = $("<div></div>")
.height(1)
.width($('#logo').width())
.css('background','url('+$('#logo').attr('src')+') no-repeat 0 ' + (-i));
$('body').append(cons);
}
}
Image on the top is just an , image on the bottom is a series of 1px tall divs.
PS Has to do with browser zoom.
It could be very slow. If you are clever you can split only as much as necessary, so there are fewer divs for the browser to deal with. I'm sure you could do it though and it might be fun.
I'm trying to figure out what the best way would be to set up a website interface that has a large centre 'tile' (basically a div with rounded corners, a variable background image, and text on it) that acts as the hub of the interface, around which I have smaller tiles which are clickable as link, e.g. one tile will lead to a photo gallery etc... However I need these smaller tiles to be moveable i.e. I would like them to visibly whisk away off the screen (in a specific direction) before the next set of tiles enters the screen.
(Ideally they would be the same set of tiles, they would simply go off screen to 'change' as it were and come back as the new set of tiles - An ideal example would be of clicking on the photo gallery tile, all the main tiles whisk away off screen, to be replaced by more tiles representing individual photos in the gallery)
I have no issues with the CSS of round corners and positioning my tiles etc... but I'm currently trying to get the tiles to actually move using the code referenced here: Alter CSS class attributes with javascript?
I can't get it to work. I've set up one of my test tiles to make just one change to the width of another test tile using the above-referenced code when it detects a mouseover event on the div, but it appears not to work.
Here's my code, if you can spot any errors, but primarily I'd also like to hear if you have any better suggestions of reaching the design state I'm looking for:
var style;
function changeFoo() {
if(typeof style == 'undefined') {
var append = true;
style = document.createElement('style');
}
else {
while (style.hasChildNodes()) {
style.removeChild(style.firstChild);
}
}
var head = document.getElementsByTagName('head')[0];
var rules = document.createTextNode(
'.tiletest2 { border:4px solid #999; background-color:#999; width: 50px; border-radius:32px; }'
);
style.type = 'text/css';
if(style.styleSheet) {
style.styleSheet.cssText = rules.nodeValue;
} else {
style.appendChild(rules);
}
if(append === true) head.appendChild(style);
}
The onmouseover event looks like this:
<div class="tiletest1" onmouseover="changeFoo()">
<br/><br/>
SAMPLE left
<br/><br/>
Try using a JavaScript library like http://jquery.com/. You can also get plugins like http://jqueryui.com/ for the kinds of effects you're describing.
I agree with TimS to go with jquery, specifically you will want to use the .animate()function.
This will make it much easier on yourself since you can easily control the speed and time the animation plays and you may be able to easily remove div(s) with the .hide() function, which gives you many options of what kind of animation you could use to close it.
I have a webpage where I want the user to see a new image when they put thier mouse over a certain part of the image. I used an image map.
<img src="pic.jpg" usemap="#picmap" />
<map id="picmap" name="picmap"><area shape="rect" coords ="10,20,30,40"
onMouseOver="mouse_on_write('mouse is on spot')"
onMouseOut="mouse_off('mouse is off spot')"
href="http://www....html" target="_blank" />
</map>
<p id="desc"></p>
Where in the header I defined these functions:
<script type="text/javascript">
function mouse_off(txt)
{
document.getElementById("desc").innerHTML=txt;
document.p1.src="pic.jpg";
}
function mouse_on_write(txt)
{
document.getElementById("desc").innerHTML=txt;
document.p1.src="pic2.jpg";
</script>
It works, but it is slow. When the mouse is put over the second image it takes some few seconds to appear; my temporary solution was to drastically reduce the size of the images because they were huge (at 2.5mb they switch fast now, but still not seamless). How can I make the image switching more seamless without reduction in picture quality?
On second thought I realize that I could also just have both images displayed, at a small and a large scale, and on mouse over they would switch places; How would I do this? Would this reduce lag?
You don't need to create any page elements, it can all be preloaded using JavaScript:
tempImg = new Image()
tempImg.src="pic2.jpg"
EDIT:
If you have a lot of images, you can use the poor-man's multi-preloader:
preloads = "red.gif,green.gif,blue.gif".split(",")
var tempImg = []
for(var x=0;x<preloads.length;x++) {
tempImg[x] = new Image()
tempImg[x].src = preloads[x]
}
Doing this with sprites is a good solution, because you don't have to wait to load the new image. Sprites work by combining the two images into one, and changing the background offset on mouseover.
You can even do with with CSS instead, for much faster results. There's a good tutorial on this here.
As of Javascript 1.6 this can be accomplished without any named variables:
imageList.forEach( function(path) { new Image().src=path } );
You can also put both images in same file and offset it up and down. If it should affect element you are crossing over with mouse it could look like
a {
background-image: url(back.png);
background-repeat: no-repeat;
background-attachment:fixed;
background-position: 0 0;
}
a:hover {
background-image: url(back.png);
background-repeat: no-repeat;
background-attachment:fixed;
background-position: 0 20px;
}
This way it can work without javascript.
If I understand your case correctly you still need javascript, but you can "preload" image this way nevertheless.
What you want todo is preload the images behind the scenes.
Then, when moused over, the browser will already have that image in its cache and will switch it over very fast.
function preloadImage(imagePath)
{
var img = document.createElement('IMG');
img.src = imagePath;
}
preloadImage('BigImage');
Clever solution from Diodeus. However, unless there's a good reason NOT TO, you should really consider using sprites. It's a bit of work to get them setup, but the net efficiency is really worth it.
This approach is the number one rule in Steve Souder's High Performance Web Sites.
"Rule 1 - Make Fewer HTTP Requests"
Good luck and have fun. - D.
I've noticed that 'preloading' into .src to this day doesn't work consistently across all browsers - IE7 still can't figure out how to cache / use preloaded images - you can clearly see there's a server request made every time you mouse over.
What I do is load in all images via standard HTML placement and just toggle style.display on and off.
Use display: none;, then have the Javascript change it to display: inline when you want to display it. This has the added advantage of being able to put the image exactly where you want in the page's source, rather than having to add it with Javascript later.
Here's how I do it, in pure JavaScript:
var myImgs = ['path/to/img1.jpg', 'path/to/img2.gif'];
function preload(imgs) {
var img;
for (var i = 0, len = imgs.length; i < len; ++i) {
img = new Image();
img.src = imgs[i];
}
}
preload(myImgs);
That said, ALassek's suggestion of using CSS sprites is an excellent one, if you have scope to do it. The advantages of sprites are many: fewer HTTP requests, smaller download size (usually), works without JavaScript enabled.
http://www.filamentgroup.com/lab/update_automatically_preload_images_from_css_with_jquery/
When we first launched the lab, we released a jQuery plugin that automatically preloads all images referenced in CSS files. We've found the script to be incredibly helpful in developing snappy applications where images are always ready when we need them. This post describes a significant update to the script which will make it even easier to integrate in existing projects.