This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm currently writing a website with a friend and I need to create a javascript loop for pulling images out of a database and populating them in xy positions on a grid.
The database we're using is built in python and django but for now I'm trying to get it working with one loop and a test image.
This is the loop in question:
function createImages(){
var picture = document.createElement('img');{
for (var pic=0; pic < 100; pic++) {
pic.pk = 1;
pic.model = 'image';
pic.fields.title = 'Image Test';
pic.fields.timestamp = '2013-01-01T00:00:00.000Z';
pic.fields.image = 'http://i240.photobucket.com/albums/ff301/quyenhiepkhach/CAT.jpg';
pic.fields.height = 30 + 'px';
pic.fields.width = 30 + 'px';
pic.fields.link = '#ImageLink';
pic.fields.board = 1;
pic.fields.posx = 100 + 'px';
pic.fields.posy = 50 + 'px';
pic.fields.owner = 1;
pic.fields.region = 1;
picture.className = 'image-tooltip';
picture.src = pic.fields.image;
picture.style.marginTop = pic.fields.posy;
picture.style.marginLeft = pic.fields.posx;
picture.style.height = pic.fields.height;
picture.style.width = pic.fields.width;
document.body.appendChild(picture);
}
}
};
createimages();
What I have working so far:
Grid that is drawn onto my index page with two sections (prime and
standard).
Mouseover script that displays the xy coords and standard or prime
gridspace. (not working in jsfiddle)
What I have broken so far:
Javascript loop for pulling images out of database and writing them to body of page
Mouseover script to display some of the image data
I've included everything below to make the webpage and also a jsFiddle
HTML HEAD:
<!-- Le random script for mouseover -->
<script type="text/javascript" src="http://code.jquery.com/jquery-git.js"></script>
<!--MOUSEOVER SCRIPT FOR GRID COORDINATES-->
<script>
$(window).load(function(){
var tooltip = $( '<div id="tooltip">' ).appendTo( 'body' )[0];
$( '.coords' ).
each(function () {
var pos = $( this ).offset(),
top = pos.top,
left = pos.left,
width = $( this ).width(),
height = $( this ).height();
$( this ).
mousemove(function ( e ) {
var x = ( (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft) - left ) .toFixed( 0 ),
y = ( ( (e.clientY + document.body.scrollTop + document.documentElement.scrollTop) - top ) ) .toFixed( 0 );
if ( x > 20 && x < 481 && y > 20 && y < 321) {
$( tooltip ).text( 'prime | ' + x + ', ' + y ).css({
left: e.clientX + 20,
top: e.clientY + 10
}).show();
}
else {
$( tooltip ).text( 'standard | ' + x + ', ' + y ).css({
left: e.clientX + 20,
top: e.clientY + 10
}).show();
}
}).
mouseleave(function () {
$( tooltip ).hide();
});
});
});
</script>
<!--MOUSEOVER SCRIPT FOR IMAGES-->
<script>
$(window).load(function(){
var imagetooltip = $( '<div id="imagetooltip">' ).appendTo( 'body' )[0];
$( '.image-tooltip' ).
each(function () {
$( imagetooltip ).text( pic.fields.title + ' , ' + pic.fields.link ).css({
left: e.clientX + 20,
top: e.clientY + 10
}).show();
mouseleave(function () {
$( tooltip ).hide();
});
});
});
</script>
CSS:
/* Style for standard section on grid */
.grid {
margin: 0px auto auto;
border: 1px solid #000;
border-width: 0 1px 1px 0;
background-color: #28ACF9;
}
/* Style for grid div */
.grid div {
border: 1px solid #000;
border-width: 1px 0 0 1px;
float: left;
}
/* Style for prime section on grid */
.gridprime {
margin-top: 50px ;
margin-left: 50px;
border: 1px solid #000;
background-color: #FFFF33;
float: left;
}
/* Style for grid coords tooltip */
#tooltip {
text-align:center;
background:black;
color:white;
padding:3px 0;
width:150px;
position:fixed;
display:none;
white-space:nowrap;
z-index:3;
}
/* Style for image tooltip */
#imagetooltip {
text-align:left;
background:#CCC;
color:white;
padding:3px 0;
width:200px;
position:fixed;
display:none;
white-space:nowrap;
z-index:4;
}
HTML BODY:
<!--SCRIPT TO CREATE THE GRID (WORKING)-->
<script type="text/javascript">
function creategrid(size){
var primeW = Math.floor((460) / size),
primeH = Math.floor((300) / size),
standardW = Math.floor((500) / size),
standardH = Math.floor((500) / size);
var standard = document.createElement('div');
standard.className = 'grid coords';
standard.style.width = (standardW * size) + 'px';
standard.style.height = (standardH * size) + 'px';
standard.board = '1';
var prime = document.createElement('div');
prime.className = 'gridprime';
prime.style.width = (primeW * size) + 'px';
prime.style.height = (primeH * size)+ 'px';
prime.style.position = 'absolute'
prime.style.zIndex= '1';
standard.appendChild(prime);
for (var i = 0; i < standardH; i++) {
for (var p = 0; p < standardW; p++) {
var cell = document.createElement('div');
cell.style.height = (size - 1) + 'px';
cell.style.width = (size - 1) + 'px';
cell.style.position = 'relative'
cell.style.zIndex= '2';
standard.appendChild(cell);
}
}
document.body.appendChild(standard);
}
creategrid(10);
</script>
<!--SCRIPT TO LOOP IMAGES OUT OF DATABASE (USING 1 TO TEST FOR NOW)-->
<script type="text/javascript">
function createImages(){
var picture = document.createElement('img');{
for (var pic=0; pic < 100; pic++) {
pic.pk = 1;
pic.model = 'image';
pic.fields.title = 'Image Test';
pic.fields.timestamp = '2013-01-01T00:00:00.000Z';
pic.fields.image = 'http://i240.photobucket.com/albums/ff301/quyenhiepkhach/CAT.jpg';
pic.fields.height = 30 + 'px';
pic.fields.width = 30 + 'px';
pic.fields.link = '#ImageLink';
pic.fields.board = 1;
pic.fields.posx = 100 + 'px';
pic.fields.posy = 50 + 'px';
pic.fields.owner = 1;
pic.fields.region = 1;
picture.className = 'image-tooltip';
picture.src = pic.fields.image;
picture.style.marginTop = pic.fields.posy;
picture.style.marginLeft = pic.fields.posx;
picture.style.height = pic.fields.height;
picture.style.width = pic.fields.width;
if (pic.fields.board = document.body.id);{
document.body.appendChild(picture);
}
}
}
};
createimages();
</script>
Your code is riddled with syntax errors and logic issues. STart by using a browser console to look at errors and fix accordingly.
Also note javascript is case sensitive so if you create a function createImages() you need to use same case to call function. You are calling createimages() which doesn't exist
You can't use pic as variable to create an object in a for loop where pic is the counter.
ALso need to create the new image within the loop, not outside it.
Working code:
//SCRIPT TO LOOP IMAGES OUT OF DATABASE (USING 1 TO TEST FOR NOW)//
function createImages() {
for (var pic = 0; pic < 100; pic++) {
/* new image for each pass of loop*/
var picture = document.createElement('img');
var data = {
pk: 1,
model: 'image',
fields: {
title: 'Image Test',
timestamp: '2013-01-01T00:00:00.000Z',
image: 'http://i240.photobucket.com/albums/ff301/quyenhiepkhach/CAT.jpg',
height: 30 + 'px',
width: 30 + 'px',
link: '#ImageLink',
board: 1,
posx: 100 + 'px',
posy: 50 + 'px',
owner: 1,
region: 1
}
};
picture.className = 'image-tooltip';
picture.src = data.fields.image;
picture.style.marginTop = data.fields.posy;
picture.style.marginLeft = data.fields.posx;
picture.style.height = data.fields.height;
picture.style.width = data.fields.width;
/* comment out "if" since isn't true*/
// if (data.fields.board ==document.body.id) {
document.body.appendChild(picture);
// }
}
}
createImages();
DEMO: http://jsfiddle.net/8eYhK/9/
There are various errors in your code
Here pic is a number, but you seem to be setting properties on it as it was an object literal
for (var pic=0; pic < 100; pic++) {
pic.pk = 1;
This line will also fail as you need to first create the pic.fields object
pic.fields = {}; // <-- add this line
pic.fields.title = 'Image Test';
Your function is called createImages but you're trying to call createimages (case-sensitivity)
I suggest you look at your browser console (usually F12) to check for errors
Related
I have this little block that I move around using javascript code. It works all good except if I keep moving it, it can easily get out of the box where it is supposed to be.
Can I prevent this somehow? So no matter how far I want to move it, it will stay stuck inside of the container/box ?
Here's my snippet code:
/// store key codes and currently pressed ones
var keys = {};
keys.UP = 38;
keys.LEFT = 37;
keys.RIGHT = 39;
keys.DOWN = 40;
/// store reference to character's position and element
var character = {
x: 100,
y: 100,
speedMultiplier: 2,
element: document.getElementById("character")
};
var is_colliding = function(div1, div2) {
var d1_height = div1.offsetHeight;
var d1_width = div1.offsetWidth;
var d1_distance_from_top = div1.offsetTop + d1_height;
var d1_distance_from_left = div1.offsetLeft + d1_width;
var d2_height = div2.offsetHeight;
var d2_width = div2.offsetWidth;
var d2_distance_from_top = div2.offsetTop + d2_height;
var d2_distance_from_left = div2.offsetLeft + d2_width;
var not_colliding =
d1_distance_from_top <= div2.offsetTop ||
div1.offsetTop >= d2_distance_from_top ||
d1_distance_from_left <= div2.offsetTop ||
div1.offsetLeft >= d2_distance_from_left;
return !not_colliding;
};
/// key detection (better to use addEventListener, but this will do)
document.body.onkeyup =
document.body.onkeydown = function(e){
if (e.preventDefault) {
e.preventDefault();
}
else {
e.returnValue = false;
}
var kc = e.keyCode || e.which;
keys[kc] = e.type == 'keydown';
};
/// character movement update
var moveCharacter = function(dx, dy){
character.x += (dx||0) * character.speedMultiplier;
character.y += (dy||0) * character.speedMultiplier;
character.element.style.left = character.x + 'px';
character.element.style.top = character.y + 'px';
};
/// character control
var detectCharacterMovement = function(){
if ( keys[keys.LEFT] ) {
moveCharacter(-5, 0);
}
if ( keys[keys.RIGHT] ) {
moveCharacter(5, 0);
}
if ( keys[keys.UP] ) {
moveCharacter(0, -5);
}
if ( keys[keys.DOWN] ) {
moveCharacter(0, 5);
}
};
/// update current position on screen
moveCharacter();
/// game loop
setInterval(function(){
detectCharacterMovement();
}, 1000/24);
body{
display: flex;
justify-content: center;
align-items: center;
}
#character {
position: absolute;
width: 42px;
height: 42px;
background: red;
z-index:99;
}
#container{
width: 400px;
height: 400px;
background: transparent;
border:5px solid rgb(0, 0, 0);
position: relative;
overflow: hidden;
}
<div id="container">
<div id="character"></div>
</div>
PS: You can move the box using keyboard arrows.
Get the container width and height into variable and set a condition on your move
var moveCharacter = function(dx, dy){
let div_width = document.getElementById('container').clientWidth;
let div_height = document.getElementById('container').clientHeight;
if((div_width - character.x) < 50 ){ // 50 = width of character and padding
character.x = div_width - 50;
}
if(character.x < 10){ // Padding
character.x = 11;
}
if((div_height - character.y) < 50 ){
character.y = div_height - 50;
}
if(character.y < 10){
character.y = 11;
}
Thanks to a really helpful user on this website (whose name I do not know, but I wish to thank and credit him!), I got the following tip on how to store area elements in an array so that when I mouse over a coordinate, I could display all of the overlay id's of the area elements that existed at that coordinate (even if the area elements were not at the same z-level):
I'm just stuck on one thing- once I have gathered all the elements that exist at the coordinate in the hoveredElements array, how do I show their overlay ids?
EDIT:
Here is an example of the full code (the overlay still does not display when I mouse over)
The file test.txt contains:
cscCSL1A15 700 359 905 318
cscCSL1A14 794 400 905 318
I use the maphilight plugin available online, and blanketaphi.png is the plot I use as a background.
<!DOCTYPE html>
<html>
<head>
<title>Detector Elements</title>
<script type="text/javascript"
src="Demo_imagemap_highlight_files/jquery-1.js"></script>
<!-- add maphilight plugin -->
<script type="text/javascript"
src="Demo_imagemap_highlight_files/jquery_002.js"></script>
</head>
<body>
<div class="content">
<div class="map"
style='display: block; background: transparent
url("Demo_imagemap_highlight_files/blanketaphi.png")
repeat scroll 0% 0%; position: relative; padding: 0px; width: 1037px;
height: 557px;'>
<canvas width="1037" height="557" style="width: 1037px; height: 557px;
position: absolute; left: 0px; top: 0px; padding: 0px; border: 0px none;
opacity: 1;"></canvas>
<img style="opacity: 0; position: absolute; left: 0px; top: 0px; padding: 0px;
border: 0px none;" src="Demo_imagemap_highlight_files/blanketaphi.png"
alt="foo" class="map maphilighted" usemap="#demo" height="557" width="1037"
border="0" />
</div>
</div>
<map name="demo" id="demo"></map>
</body>
</html>
<script type="text/javascript">
window.onload = function(){
var f = (function(){
var xhr = [];
var files = [ "test.txt"];
for (i = 0; i < 1; i++) {
(function (i){
xhr[i] = new XMLHttpRequest();
xhr[i].open("GET", files[i], true);
xhr[i].onreadystatechange = function () {
if (xhr[i].readyState == 4 && xhr[i].status == 200) {
// get text contents
j=20000*i + 50000;
var coords = xhr[i].responseText.split("\n");
coords = coords.filter(Boolean) //prevents extra rect with 0 coords
coords.forEach(function(coord) {
var area = document.createElement("area");
var att = document.createAttribute("data-maphilight");
if (i == 0) { //green
att.value = '{"strokeColor":"000000","strokeWidth":2,' +
'"fillColor":"009900","fillOpacity":0.5}';
}
area.setAttributeNode(att);
area.id = "r"+j;
area.shape = "rect";
area.coords = coord.substring(10,coord.length).trim()
.replace(/ +/g,","); // replaces spaces in txt file with commas
area.href = "#";
area.alt = "r"+j;
// create overlay with first term in string
var div = document.createElement("div");
div.id ="overlayr"+j;
div.innerHTML = coord.substring(0,10);
div.style.display = "none";
//increase j
j++;
// get map element
document.getElementById("demo").appendChild(area);
document.getElementById("demo").appendChild(div);
});
$('.map').maphilight();
//display overlay ids by mousing over
var elementPositions = [];
var hoveredElements = [];
if($('#demo')) {
$('#demo area').each(function() {
var offset = $(this).offset();
var top = offset.top;
var left = offset.left;
var bottom = $(window).height() - top - $(this).height();
var right = $(window).width() - left - $(this).width();
elementPositions.push({
element: $(this),
top: top,
bottom: bottom,
left: left,
right: right
});
//alert(top + "," + left + "," + right + "," + bottom);
});
$("body").mousemove(function(e) {
hoveredElements = [];
var yPosition = e.pageX;
var xPosition = e.pageY;
for (var i = 0; i < elementPositions.length; i++) {
if (xPosition >= elementPositions[i].left &&
xPosition <= elementPositions[i].right &&
yPosition >= elementPositions[i].top &&
yPosition <= elementPositions[i].bottom) {
// The mouse is within the element's boundaries
$("#hovers").append(elementPositions[i].element);
}
}
for (var i = 0; i < hoveredElements.length; i++) {
// The element as a jQuery object
var elem = hoveredElements[i];
var id = hoveredElements[i].attr('id');
$('#overlay'+id).show();
}
});
};
}
};
xhr[i].send();
})(i);
}
})();
};
</script>
Why not just something like this:
var elementPositions = [];
var hoveredElements = [];
if($('#demo')) {
$('#demo area').each(function() {
var offset = $(this).offset();
var top = offset.top;
var left = offset.left;
var bottom = $(window).height() - top - $(this).height();
var right = $(window).width() - left - $(this).width();
elementPositions.push({ element: $(this), top: top, bottom: bottom, left: left, right: right });
//alert(top + "," + left + "," + right + "," + bottom);
});
$("body").mousemove(function(e) {
hoveredElements = [];
var yPosition = e.pageX;
var xPosition = e.pageY;
for (var i = 0; i < elementPositions.length; i++) {
if (xPosition >= elementPositions[i].left &&
xPosition <= elementPositions[i].right &&
yPosition >= elementPositions[i].top &&
yPosition <= elementPositions[i].bottom) {
// The mouse is within the element's boundaries
hoveredElements.push(elementPositions[i].element);
$("#hovers").append(elementPositions[i].element);
}
} //end of for loop over all elements
console.log(hoveredElements);
for (var i = 0; hoveredElements.length; i++)
{ //for loop over all hovered elements
// The element as a jQuery object
var elem = hoveredElements[i];
var id = hoveredElements[i].attr('id');
console.log(id);
$('#overlay'+id).show();
// Do stuff to that jQuery element:
//??? something like elem.show();
}
You've got a lot of stuff here that doesn't make sense to me but here's what I can gather so far.
Your areas need to be in a container called demo area. Not sure how the space in the ID works so in my case I switched it to demoarea. Also somewhere in the page, there has to be another element called demo for anything to even happen.
Once that's done, the script loads demoarea into the elementPositions array. Judging from your description that's not what you want to do, you probably want to load all the elements inside demoareainto the array. So the first change is
$('#demo area').each(function() {
Becomes
$('#demoarea').children().each(function() {
Now what becomes confusing to me is that this script for whatever reason decides that you need to have another element called hover so it can move the element out of demoarea into hover when you mouse over it. If that is what you want, then you can do your show trick with some simple CSS.
<div style="display:none" id="overlayr6064"> Example Overlay ID name </div>
Becomes
<div id="overlayr6064"> Example Overlay ID name </div>
And then you add:
<style>
#demoarea div {
display: none;
}
#hover div {
display: block;
}
</style>
Assuming that is not what you wanted, what #liamEgan did to add the elements to the hoveredElements array is good, but you have an infinite loop here
for (var i = 0; hoveredElements.length; i++)
it should be
for (var i = 0; i < hoveredElements.length; i++)
Then the rest works... except one last thing, you want to load these listeners to your script when the page loads in a document ready method.
So in all it looks a bit like:
//display overlay ids by mousing over (my map is called 'demo')
var elementPositions = [];
var hoveredElements = [];
if($('#demo')) {
$('#demoarea').children().each(function() {
var offset = $(this).offset();
var top = offset.top;
var left = offset.left;
var bottom = $(window).height() - top - $(this).height();
var right = $(window).width() - left - $(this).width();
elementPositions.push({ element: $(this), top: top, bottom: bottom, left: left, right: right });
});
console.log('After Scanning demoarea elementPositions looks like:')
console.log(elementPositions);
$(document).ready(function () {
$("body").mousemove(function(e) {
hoveredElements = [];
var yPosition = e.pageX;
var xPosition = e.pageY;
for (var i = 0; i < elementPositions.length; i++) {
if (xPosition >= elementPositions[i].left &&
xPosition <= elementPositions[i].right &&
yPosition >= elementPositions[i].top &&
yPosition <= elementPositions[i].bottom) {
// The mouse is within the element's boundaries
if (typeof elementPositions[i].element != "undefined") {
hoveredElements.push(elementPositions[i].element);
$("#hovers").append(elementPositions[i].element);
}
}
} //end of for loop over all elements
for (var i = 0; i < hoveredElements.length; i++) { //for loop over all hovered elements
// The element as a jQuery object
console.log(hoveredElements[i]);
if (typeof hoveredElements[i] != "undefined") {
var elem = hoveredElements[i];
var id = elem.attr('id');
$('#overlay'+id).show();
}
// Do stuff to that jQuery element:
//??? something like elem.show();
}
});
});
}
#demoarea {
border: 2px blue dotted;
}
/* Border added so I can see where to mouse over */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="demo">
<div id="demoarea">
<area shape="rect" coords="431,499,458,491" href="#" id="r6064" alt="r6064">
<div style="display:none" id="overlayr6064"> Example Overlay ID name </div>
</div>
<div id="hovers">
</div>
</div>
Edit: sorry I added the undefined tests while fixing this because of the infinite loop but I think they're not really needed. Still nice to have though. Also since the area also gets moved into the hover area this script does try to show an element called overlayoverlayr6064r6064 which fortunately doesn't exist. But ya, again, probably not what you had in mind.
I'm working on Some JS project And I'm trying to change scrolling speed and scroll to next division height of 100% ...
My idea for scrolling Down >
Detect InnerHTML height + detect scroll space from top , detect position using innerHTML height and a counter ....
when user scrolles down for fisrt time , position is 0 and scrollTop is more, so function is called and brings user to next div . (its OK)
but then ,what can I do to bring user back to previous div when user scrolls UP ?
Here are my codes :
<html>
<head>
<style>
body,html {
margin: 0;
height: 100%;
width: 100%;
}
.scrollers {
height: 100%;
width: 100%;
transition: all 1s;
-webkit-transition: all 1s;
}
#N1 {
background-color: #725a5a;
}
#N2 {
background-color: #4a478d;
}
#N3 {
background-color: #478d6f;
}
#N4 {
background-color: #8d8a47;
}
#status {
text-align: center;
width: 100%;
color: #000;
font-size: 20px;
position: fixed;
z-index: 10;
top: 5px;
}
</style>
<script>
var $firstPosition = 1;
window.onscroll = scroll;
var $counter = 0;
var $status = "play";
function scroll() {
var $sctop = document.body.scrollTop;
var $inrH = window.innerHeight;
var $secst;
if (($status=="pause") || ($secst=="pause")){
} else if ($status=="play"){
var $position = $counter * $inrH;
if ($sctop>$position) {
$counter++;
$position = $counter * $inrH;
$status = "pause";
$secst = "pause";
callMeInterval = setInterval( function() { if(!($sctop==$position)){window.scrollTo(0,$firstPosition);$firstPosition++;$sctop = document.body.scrollTop;document.getElementById("status").innerHTML = "sctop = " + $sctop + " $position = " + $position + "$counter = " + $counter; } else if($sctop==$position) {$status = "play";secst==""} }, 1 );
}
// Problem Starts Here
else {
$counter--;
$position = $counter * $inrH;
$status = "pause";
$secst = "pause";
callMeInterval = setInterval( function() { if(!($sctop==$position)) {$firstPosition--;window.scrollTo(0,$firstPosition);$sctop = document.body.scrollTop;document.getElementById("status").innerHTML = "sctop = " + $sctop + " $position = " + $position + "$counter = " + $counter; } else if($sctop==$position) {secst=="";$status = "play"} }, 1 );
}
}
}
</script>
</head>
<body>
<div id="status">
</div>
<div id="N1" class="scrollers">
</div>
<div id="N2" class="scrollers">
</div>
<div id="N3" class="scrollers">
</div>
<div id="N4" class="scrollers">
</div>
</body>
</html>
I'm sure the whole thing is just easier with JQUERY , but this is my project for Javascript Class . Thanks
You don't clear your interval, so this is the reason of flickering.
clearInterval(callMeInterval);
I recommend you to use requestAnimationFrame instead of using window.setInterval
Here you have working sample rebuild with requestAnimationFrame
var lastScrollPosition = document.body.scrollTop,
sectionNo = 0;
function doScroll(scrollPosition, step, first) {
var height = window.innerHeight,
min = height * sectionNo,
max = height * (sectionNo + 1);
scrollPosition += step;
if (min < scrollPosition && scrollPosition < max) {
// here should be some animation control
document.body.scrollTop = scrollPosition;
// Call next animation frame
window.requestAnimationFrame(doScroll.bind(null, scrollPosition, step));
} else {
// It fires, when scroll is done
lastScrollPosition = scrollPosition;
document.addEventListener("scroll", scrollListener);
}
}
function scrollListener(e) {
var scrollPosition = document.body.scrollTop,
step;
// Stop scroll listening
document.removeEventListener("scroll", scrollListener);
// Get direction
step = scrollPosition >= lastScrollPosition ? 5 : -5;
// Go back to initial position
document.body.scrollTop = lastScrollPosition;
// Animate
window.requestAnimationFrame(doScroll.bind(null, lastScrollPosition, step, true));
}
document.addEventListener("scroll", scrollListener);
origin
result
I want to split a string into character, and make each of the character fit the container equally, this is my work for the time being: http://jsfiddle.net/d5fu9/
The first item must attached to the left, and the last item must attached to the right.
$.fn.textjustify = function() {
return this.each(function() {
var text = $(this).text(),
containerWidth = $(this).width(),
character = '',
string = '',
singleWidth = 0,
firstItemWidth = 0,
lastItemWidth = 0,
alignWidth = 0;
if ('' !== text) {
$(this).css('position', 'relative');
textArray = text.split('');
singleWidth = Math.floor(containerWidth / textArray.length);
for (i in textArray) {
// Wrapp with div to get character width
character = ('' === $.trim(textArray[i])) ? ' ' : textArray[i];
string += '<span>' + character + '</span>';
}
$(this).html(string);
firstItemWidth = $(this).find('span:first').width();
lastItemWidth = $(this).find('span:last').width();
alignWidth = containerWidth - (firstItemWidth + lastItemWidth);
$(this).find('span').each(function(i) {
if (0 === parseInt(i)) {
// The first item
$(this).css({position: 'absolute', left: 0, top: 0});
} else if ((parseInt(textArray.length) - 1) === parseInt(i)) {
// The last item
$(this).css({position: 'absolute', right: 0, top: 0});
} else {
// Other items
// stuck in here......
var left = (i * singleWidth) - $(this).width() + firstItemWidth;
$(this).css({position: 'absolute', left: left, top: 0});
}
});
}
});
}
stuck in the algorithm of middle items's position.
I think this is the simplest solution.
Works great with All browsers (IE included)
without complex (and unreliable) width detection and calculation.
without specifying the words width/height
without relative/absolute positioning
using pure HTML/CSS/JS/JQ tricks.
Working Fiddle
HTML:(very simple)
<div class="Box">
<div class="Centered">
<div class="Spread">Lighting</div>
<div class="Spread">我是中文</div>
</div>
</div>
CSS:(neat and tricky)
*
{
margin: 0;
padding: 0;
}
.Box
{
width: 150px;
height: 150px;
border: 1px solid red;
margin: 6px;
}
.Box:before
{
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-left: -5px;
}
.Centered
{
display: inline-block;
vertical-align: middle;
width: 100%;
}
.Spread
{
width: 100%;
text-align: justify;
font-size: 0;
}
.Spread span
{
font-size: medium;
}
.Spread:after
{
content: '';
display: inline-block;
height: 0px;
width: 100%;
}
JS/JQ:
$.fn.SplitText = function () {
return this.each(function () {
return $(this).html('<span>' + $(this).text().split('').join(' ') + '</span>');
});
}
$(function () {
$('.Spread').SplitText();
})
Explanations:
as mentioned by wared in the comments, IE7 doesn't support the use of pseudo classes.
but they are not necessary for the solution. Here's a Fiddle for IE7 (and all other browsers of course).
how the vertical aligning works?
when vertical-align:middle; is used on an inline element, it will align the middle of this element with the other inline elements in the same line.
that's why I'm creating an inline element with height:100%;, so when we align our inline element to his middle, it will actually be the middle of the container.
how the horizontal distribution works?
taking advantage of the text-align:justify;,
we create an empty inline element (height:0;) with width:100%;, we can imagine that it takes a full line, and the rest of the text takes the second line.
using justify makes the second line spread evenly to take the exact space as the first.
let me know if you need more explanation.
I added a fixed with for spanelements for the widest char which was W in your fiddle with 15px.
span {
width: 15px;
}
Then substracted 20px from container width which will be the free space on the sides later.
singleWidth = Math.floor((containerWidth-20) / textArray.length);
Added this extra Space to the firstitemWidth so that the other chars align correctly:
firstItemWidth = $(this).find('span:first').width() + 10;
And set the position of first and last to 10 from left and right here:
if (0 === parseInt(i)) {
// The first item
$(this).css({position: 'absolute', left: 10, top: 0});
} else if ((parseInt(textArray.length) - 1) === parseInt(i)) {
// The last item
$(this).css({position: 'absolute', right: 10, top: 0});
Here is the updated Fiddle
I hope this will work out for you ;)
I have made a script for you if you do not mind left and right spaces. You can set the right and left margins making some little modifications.
$(document).ready(function(){
var txt = $(".container").text(); //get the text
var txt2 = "";
var len = txt.length;
$(".container").empty(); //clear the content
for(i=0; i<len; i++) //surround all characters with span
{
txt2 += "<span>" + txt.substr(i,1) + "</span>";
}
$(".container").html(txt2);
$("span").css({"width": Math.round($(".container").width())/len + "px", "display":"inline-block", "text-align":"center"});
});
Fiddle is here
Try this:
DEMO: http://jsfiddle.net/jc2mm/4/
JS:
$(".spread").each(function(idx, elem) {
var titleElem = $(this),
titleStr = titleElem.html(),
charWidth = Math.floor(($(".box").width() / titleStr.length) * 100) / 100;
titleElem.html("");
for(var i = 0; i < titleStr.length; i++) {
titleElem.append($("<span>", {"class" : "singleChar"}).css("width", charWidth).html(titleStr[i]));
}
});
CSS:
.box {
width: 150px;
height: 150px;
border: 1px solid red;
margin: 6px;
}
.title {
margin-top: 40px;
height: 16px;
}
.singleChar {
float: left;
text-align: center;
display: block;
min-height: 1px;
}
Try this: http://jsfiddle.net/d5fu9/5/
Each character is contained in a box of width singleWidth, left is computed counting the preceding character boxes, characters are centered.
Changes:
$(this).css({width: singleWidth,position: 'absolute', left: 0, top: 0});
and
var left = i* singleWidth + (i-1)*(textArray.length-2)/(textArray.length+1);
and in CSS:
.spread {
text-align: center;
}
Here is another version http://jsfiddle.net/d5fu9/6/ where leftmost and rightmost characters are attached to the border.
Modified width of a single character container:
singleWidth = Math.floor((containerWidth -firstItemWidth - lastItemWidth)/ (textArray.length-2));
and how much each inner character moves from the left:
var left = firstItemWidth+(i-1)* singleWidth ;
I've made this stuff : http://jsfiddle.net/wared/HDbA5/.
The idea is to use paddings to create space between chars. Tested with Chrome only. It seems to fail when the DIV has no explicit fixed width, and sometimes there is one pixel remaining, I haven't investigated. Lastly, this script does not support single characters. If you're interested in this answer, this job is for you :)
I must show some code to be able to post this answer, so, here it is :
<div><span>hello</span></div>
jQuery.fn.justify = function () {
return this.each(function () {
var el = $(this),
ct = el.parent(),
chars = el.text().split(''),
bits = (chars.length - 1) * 2,
freeSpace = ct.width() - el.width(),
bitWidth = Math.floor(freeSpace / bits),
gap = freeSpace % bits;
el.html(jQuery.map(chars, function (char, i) {
var paddings = ['0', null, '0', null];
if (!i) {
paddings[1] = (bitWidth + (gap && (--gap, 1))) + 'px';
paddings[3] = '0';
} else if (i + 1 === chars.length) {
paddings[1] = '0';
paddings[3] = (bitWidth + (gap && (--gap, 1))) + 'px';
} else {
paddings[1] = (bitWidth + (gap && (--gap, 1))) + 'px';
paddings[3] = (bitWidth + (gap && (--gap, 1))) + 'px';
}
return '<span style="padding:' + paddings.join(' ') + '">' + char + '</span>';
}).join(''));
});
};
A "bit" is a portion of the free space. It's half the space between two characters :
"abc" : 4 bits ("a..b..c").
"ab cd" : 8 bits ("a..b.. ..c..d").
The "gap" is the number of pixels remaining after splitting the free space into bits. Those pixels are assigned to each "bit" until no pixels remain. Let's say gap = 1 :
bitWidth + (gap && (--gap, 1)) // gap = gap - 1 THEN bitWidth + 1
// next bit
bitWidth + (gap && (--gap, 1)) // bitWidth + 0
My client is using the "Digg-Digg" plugin on their blog, and has asked me to implement the same thing on the rest of the site. I have copied the html code, the css file & the JS file, updated the links and variables, yet it still won't appear on the page. Can anyone help me out??? Thank you in advance.
Here is the html code:
<a id="dd_end"></a>
<div class='dd_outer'>
<div class='dd_inner'>
<div id='dd_ajax_float' style="position: absolute; top: 308px; left: -95px; display: block;">
<div class='dd_button_v'>
<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://www.scottera.com/" data-count="vertical" data-text="Arch Kit" data-via="archkit" ></a><script type="text/javascript" src="//platform.twitter.com/widgets.js"></script></div><div style='clear:left'></div><div class='dd_button_v'><script src="//connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:like href="http://www.scottera.com" send="false" show_faces="false" layout="box_count" width="50" ></fb:like></div><div style='clear:left'></div><div class='dd_button_v'><script type='text/javascript' src='https://apis.google.com/js/plusone.js'></script><g:plusone size='tall' href='http://www.scottera.com/'></g:plusone></div><div style='clear:left'></div></div></div></div><script type="text/javascript">var dd_offset_from_content = 40;var dd_top_offset_from_content = 0;var dd_override_start_anchor_id = "";var dd_override_top_offset = "";</script><script type="text/javascript" src="include/digg-digg/js/diggdigg-floating-bar.js?ver=5.3.6"></script>
And here is the CSS for the main sections:
.dd_outer {
width:100%;
height:0;
position:absolute;
top:0;
left:0;
z-index:9999
}
.dd_inner {
margin:0 auto;
position:relative
}
EDIT: Adding JS code:
var dd_top = 0;
var dd_left = 0;
jQuery(document).ready(function(){
var $floating_bar = jQuery('#dd_ajax_float');
var dd_anchorId = 'dd_start';
if ( typeof dd_override_start_anchor_id !== 'undefined' && dd_override_start_anchor_id.length > 0 ) {
dd_anchorId = dd_override_start_anchor_id;
}
var $dd_start = jQuery( '#' + dd_anchorId );
var $dd_end = jQuery('#dd_end');
var $dd_outer = jQuery('.dd_outer');
// first, move the floating bar out of the content to avoid position: relative issues
$dd_outer.appendTo('#wrapper');
if ( typeof dd_override_top_offset !== 'undefined' && dd_override_top_offset.length > 0 ) {
dd_top_offset_from_content = parseInt( dd_override_top_offset );
}
dd_top = parseInt($dd_start.offset().top) + dd_top_offset_from_content;
if($dd_end.length){
dd_end = parseInt($dd_end.offset().top);
}
dd_left = -(dd_offset_from_content + 55);
dd_adjust_inner_width();
dd_position_floating_bar(dd_top, dd_left);
$floating_bar.fadeIn('slow');
if($floating_bar.length > 0){
var pullX = $floating_bar.css('margin-left');
jQuery(window).scroll(function () {
var scroll_from_top = jQuery(window).scrollTop() + 30;
var is_fixed = $dd_outer.css('position') == 'fixed';
if($dd_end.length){
var dd_ajax_float_bottom = dd_end - ($floating_bar.height() + 30);
}
if($floating_bar.length > 0)
{
if(scroll_from_top > dd_ajax_float_bottom && $dd_end.length){
dd_position_floating_bar(dd_ajax_float_bottom, dd_left);
$dd_outer.css('position', 'absolute');
}
else if ( scroll_from_top > dd_top && !is_fixed )
{
dd_position_floating_bar(30, dd_left);
$dd_outer.css('position', 'fixed');
}
else if ( scroll_from_top < dd_top && is_fixed )
{
dd_position_floating_bar(dd_top, dd_left);
$dd_outer.css('position', 'absolute');
}
}
});
}
// Load Linked In Sharers (Resolves issue with position on page)
if(jQuery('.dd-linkedin-share').length){
jQuery('.dd-linkedin-share div').each(function(index) {
var $linkedinSharer = jQuery(this);
var linkedinShareURL = $linkedinSharer.attr('data-url');
var linkedinShareCounter = $linkedinSharer.attr('data-counter');
var linkedinShareCode = jQuery('<script>').attr('type', 'unparsed-IN/Share').attr('data-url', linkedinShareURL).attr('data-counter', linkedinShareCounter);
$linkedinSharer.html(linkedinShareCode);
IN.Event.on(IN, "systemReady", function() {
$linkedinSharer.children('script').first().attr('type', 'IN/Share');
IN.parse();
});
});
}
});
jQuery(window).resize(function() {
dd_adjust_inner_width();
});
var dd_is_hidden = false;
var dd_resize_timer;
function dd_adjust_inner_width() {
var $dd_inner = jQuery('.dd_inner');
var $dd_floating_bar = jQuery('#dd_ajax_float')
var width = parseInt(jQuery(window).width() - (jQuery('#dd_start').offset().left * 2));
$dd_inner.width(width);
var dd_should_be_hidden = (((jQuery(window).width() - width)/2) < -dd_left);
var dd_is_hidden = $dd_floating_bar.is(':hidden');
if(dd_should_be_hidden && !dd_is_hidden)
{
clearTimeout(dd_resize_timer);
dd_resize_timer = setTimeout(function(){ jQuery('#dd_ajax_float').fadeOut(); }, -dd_left);
}
else if(!dd_should_be_hidden && dd_is_hidden)
{
clearTimeout(dd_resize_timer);
dd_resize_timer = setTimeout(function(){ jQuery('#dd_ajax_float').fadeIn(); }, -dd_left);
}
}
function dd_position_floating_bar(top, left, position) {
var $floating_bar = jQuery('#dd_ajax_float');
if(top == undefined) top = 0 + dd_top_offset_from_content;;
if(left == undefined) left = 0;
if(position == undefined) position = 'absolute';
$floating_bar.css({
position: position,
top: top + 'px',
left: left + 'px'
});
}
You can use the floating social bar plugin
http://wordpress.org/plugins/floating-social-bar/ (it is my plugin)
There is an option to manually add the floating bar on all WordPress pages if you want. Just look at the code on the FAQ page.