Accordian Element Height Issue - javascript

I have implemented 2 types of Accordians for my application- 1 Column and 2 Column
Im having a problem with the Static Height for the 1 Column Accordian. And I've been trying to modify the JavaScript all day but cant seem to get it to work.
The Heights should be dynamic in Height depending upon the amount data, however as you can see the Height is fixed, and some of the data is getting cut off:
http://www.davincispainting.com/whydavincis.aspx
The other 2 Column Accordian has almost the same JavaScript as the 1 Column Accordian, however the Height is dynanmic depending on how much data there is:
http://www.davincispainting.com/glossary.aspx
I would provide a Fiddle however the Data is now dynamic:
Here is the JavaScript for the problem Accordian:
<script type="text/javascript">
$.fn.accordion = function () {
return this.each(function () {
$container = $('#mid-featureleft-client');
$container.find("dt").each(function () {
var $header = $(this);
var $selected = $header.next();
$header.click(function () {
$('.active').removeClass('active');
$(this).addClass('active');
if ($selected.is(":visible")) {
$selected.animate({
height: 0
}, {
duration: 300,
complete: function () {
$(this).hide();
}
});
} else {
$unselected = $container.find("dd:visible");
$selected.show();
var newHeight = heights[$selected.attr("id")];
var oldHeight = heights[$unselected.attr("id")];
$('<div>').animate({
height: 1
}, {
duration: 300,
step: function (now) {
var stepSelectedHeight = Math.round(newHeight * now);
$selected.height(stepSelectedHeight);
$unselected.height(oldHeight + Math.round((newHeight - oldHeight) * now) - Math.round(newHeight * now));
},
complete: function () {
$unselected.hide().css({
height: 0
});
}
});
}
return false;
});
});
// Iterate over panels, save heights, hide all.
var heights = new Object();
$container.find("dd").each(function () {
$this = $(this);
$this.css("overflow", "hidden");
heights[$this.attr("id")] = $this.height();
$this.hide().css({
height: 0
});
});
});
};
$(document).ready(function () {
$.getJSON('FaqsJson.ashx?factType=2', function (datas) {
var str_one = "";
str_one = "<dl>"
$.each(datas, function () {
str_one += "<dt class=\"glossquestion\">" + this['Question'] + "</dt>";
str_one += "<dd class=\"glossanswer\" style=\"-webkit-margin-start:0px\"><div class=\"answerbox\">" + this['Answer'] + "</div></dd>";
});
str_one += "</dl>";
$("#glossary_first").html(str_one);
$("#mid-featureleft-client").accordion();
});
});
</script>
Here is the relevent HTML:
<div id="mid-feature-client">
<div id="mid-featureleft-client">
<div id="glossary_first" class="controlbox">
<br /><br />
</div>
<div style="clear: both;">
</div>
</div>
</div>
Here is the relevent css:
#mid-featureleft-client .controlbox {
width:546px;
padding:3px 0 0 6px;
position:relative;
/*background-color:green;*/
}
#mid-featureleft-client .glossarycontrolbox {
width:260px;
padding:3px 0 0 6px;
position:relative;
float:left;
/*background-color:blue;*/
}
.question-clicked {
background-color: #CCCCCC;
color: #0C2A55;
/*margin-top: 10px;*/
/*padding: 2px 5px 0;*/
}
.questionLink-clicked {
color: #0C2A55;
font-size: 1.2em;
font-weight: bold;
}
.answerbox {
padding: 3px 5px 3px 5px;
}
.questionLink {
color: #0C2A55;
font-size: 1.2em;
font-weight: bold;
}
.glossquestion {
padding: 0 5px 4px 0;
}
.glossanswer {
background-color: #F9FBFC;
display: none;
}
#accordion .handle {
width: 260px;
height: 30px;
background-color: orange;
}
#accordion .section {
width: 260px;
height: 445px;
background-color: #a9a9a9;
overflow: hidden;
position: relative;
}
dt {
/*background-color: #ccc;*/
}
dd {
/*height: 30px;*/
}
.active {
background: #a9a9a9;
}

The problem is with the way you're storing the heights, a bit after this comment:
// Iterate over panels, save heights, hide all.
Specifically, this line:
heights[$this.attr("id")] = $this.height();
Your dd elements don't have an id, so on each iteration of the loop, heights[''] is being set to the height of the current dd.
You should be able to fix it by changing this:
$.each(datas, function () {
str_one += "<dt class=\"glossquestion\">" + this['Question'] + "</dt>";
str_one += "<dd class=\"glossanswer\" style=\"-webkit-margin-start:0px\"><div class=\"answerbox\">" + this['Answer'] + "</div></dd>";
});
to this:
var i = 0;
$.each(datas, function () {
str_one += "<dt class=\"glossquestion\">" + this['Question'] + "</dt>";
str_one += "<dd id=\"rand_" + i + "\" class=\"glossanswer\" style=\"-webkit-margin-start:0px\"><div class=\"answerbox\">" + this['Answer'] + "</div></dd>";
i++;
});
I'm just going to point out that my fix doesn't seem very jQuery-esque, and your entire code seems complicated for what it's doing.
If you changed your JSON to something like this:
[{"Question1":"..","Answer1":".."},{"Question2":"..","Answer2":".."}, .. ]
You could do this:
$.each(datas, function (i, v) {
str_one += "<dt class=\"glossquestion\">" + this['Question'] + "</dt>";
str_one += "<dd id=\"Dd" + i + "\" class=\"glossanswer\" style=\"-webkit-margin-start:0px\"><div class=\"answerbox\">" + this['Answer'] + "</div></dd>";
});
which is cleaner code than incrementing our own variable i inside $.each.

Related

Multiselect with jQuery and Selectable

I have problem with multiselect on jQuery with selectable.
I do have some idea of what is happening.
When splicing the items they get new index. This is what I believe is the problem. But I can't seem to find a solution.
Your help is much appreciated!
I created this JSFiddle
Here below is the same as JSFiddle. But this below does not work. I don't understand why. I had to paste the code below to be able to post.
The JSFiddle works though. So check that.
var arrSelectedItems = [];
var arrItems = [];
$("#showItems").click(function() {
arrItems.push([1, "Mr", "John", "Andersson"]);
arrItems.push([2, "Mrs", "Anna", "Svensson"]);
arrItems.push([3, "Mr", "Klas", "Olsson"]);
arrItems.push([4, "Mrs", "Lovisa", "Henriksson"]);
arrItems.push([5, "Mr", "Anders", "Annikadotter"]);
arrItems.push([6, "Mrs", "Klara", "Annasson"]);
showItems();
});
function showItems() {
$('#selectable').empty();
$(arrItems).each(function(i) {
var stringItems = arrItems[i].toString().split(",");
$('#selectable').append("<li class=\"ui-widget-content\" value='" + i + "'>" + stringItems[1] + " " + stringItems[2] + " " + stringItems[3] + "</li>").attr("class", "ui-widget-content");
});
}
function showSelectedItems() {
$('#selected').empty();
$(arrSelectedItems).each(function(i) {
var stringItem = arrSelectedItems[i].toString().split(",");
$('#selected').append("<li class=\"ui-widget-content\" value='" + i + "'>" + stringItem[2] + " " + stringItem[3] + " " + stringItem[1] + "</li>");
});
}
$(function() {
$("#selectable").selectable({
stop: function() {
$(".ui-selected", this).each(function() {
var $this = $(this);
var index = $this.attr("value");
var pushString = arrItems[index];
arrSelectedItems.push(pushString);
arrSelectedItems.sort();
arrItems.splice(index, 1);
arrItems.sort();
showItems();
showSelectedItems();
});
}
});
});
$(function() {
$("#selected").selectable({
stop: function() {
$(".ui-selected", this).each(function() {
var $this = $(this);
var index = $this.attr("value");
var pushString = arrSelectedItems[index];
arrItems.push(pushString);
arrItems.sort();
arrSelectedItems.splice(index, 1);
arrSelectedItems.sort();
showItems();
showSelectedItems();
});
}
});
});
#selectable .ui-selecting {
background: #FECA40;
}
#selectable .ui-selected {
background: #F39814;
color: white;
}
#selectable {
list-style-type: none;
margin: 0;
padding: 0;
width: 60%;
}
#selectable li {
margin: 3px;
padding: 0.4em;
font-size: 1.4em;
height: 18px;
}
#selected .ui-selecting {
background: #FECA40;
}
#selected .ui-selected {
background: #F39814;
color: white;
}
#selected {
list-style-type: none;
margin: 0;
padding: 0;
width: 60%;
}
#selected li {
margin: 3px;
padding: 0.4em;
font-size: 1.4em;
height: 18px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.1/jquery-ui.js"></script>
<input type="button" id="showItems" name="showItems" value="Show items">
<ol id="selectable" class="ui-selectable" style="background:#84ac38; border: 1px solid #267501;">
</ol>
<ol id="selected" class="ui-widget-content" style="background:#e9b91c ;border: 1px solid #ce7b12;>
</ol>
So I now understand what the problem was. When splicing a array, the next index gets the one removed. So therefore the each function does not work when splicing.
I then tried to do the each backwards, the each function would not interfere with next to be spliced. I found this super nice and clean soultion.
https://stackoverflow.com/a/5386150/2950384
Add this short jquery plugin code
jQuery.fn.reverse = [].reverse;
And use the reverse like this
stop: function() {
$(".ui-selected", this ).reverse().each(function() {
var $this = $(this);
And now the multiselect works.

How to make divs names always be 1,2,3 jQuery

My issue is that when i append 2 divs white jQuery, there names are:
This is div 1
This is div 2
But when i remove the first div (This is div 1)
and append another div
it adds one more div whit name (This is div 2):
This is div 2
This is div 2
The reason is because the name of the div counts the total amout of divs... Is there any other way to number all divs so they will always be like this:
This is div 1
This is div 2
This is div 3
Even if i the divs are:
This is div 1
This is div 6
This is div 12
I want them always to be 1,2,3
jQuery code:
$('#add_item').click(function() {
//div count
var countDivs = $("div").length;
//append content
var removeBtn = ('<a class="removeBtn">x</a>')
var h2 = ('<h2>This is div '+countDivs+'</h2>')
var appendContent = ('<div>'+h2+removeBtn+'</div>')
$('#accordion').append(appendContent);
});
//remove button
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
return false;
});
JSFIDDLE
I think you'll have to edit contents of the divs each time a div is removed.
Let's say you have an element and you want to add divs to it.
You will add like you are right now and when you remove you edit all other divs.
The code would be something like this
$('#add_item').click(function() {
var countDivs = $("div").length;
var removeBtn = ('<a class="removeBtn">x</a>')
var h2 = ('<h2>This is div '+countDivs+'</h2>')
var appendContent = ('<div class="appDiv">'+h2+removeBtn+'</div>')
$('#accordion').append(appendContent);
});
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
$('.appDiv').each(function(index,el){
$(el).find('h2').text('This is div '+(index+1));
});
return false;
});
here is the Fiddle
Hope this helps :)
Write a function to renaming the divs and call it after append/remove.
function reArrange() {
$("#accordion > div").each(function(i) {
$(this).find("h2").text("This is div" + (i + 1))
});
}
Fiddle
When an item is removed, change the title of all the elements after it.
$('#add_item').click(function() {
var countDivs = $("#accordion div").length + 1;
var removeBtn = ('<a class="removeBtn">x</a>')
var h2 = ('<h2>This is div <span>' + countDivs + '</span></h2>')
var appendContent = ('<div>' + h2 + removeBtn + '</div>')
$('#accordion').append(appendContent);
});
$(document).on('click', '.removeBtn', function() {
var $div = $(this).parent();
$div.nextAll('div').find('span').html(function(i, html) {
return --html
});
$div.remove();
return false;
});
div {
position: relative;
}
#accordion {
margin-left: 60px;
padding: 10px;
background: #ddd;
}
#add_item {
position: absolute;
top: 20px;
left: 20px;
font-size: 20px;
padding: 5px 10px;
background: black;
color: white;
cursor: pointer;
}
.removeBtn {
font-size: 20px;
padding: 2px 10px 5px;
background: black;
color: white;
cursor: pointer;
position: absolute;
top: 0px;
font-family: verdana;
border-radius: 100%;
left: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="accordion">
</div>
<a id="add_item">+</a>
you should use a global variable like "count":
var count=1;
$('#add_item').click(function() {
//div count
//var countDivs = $("div").length;
var countDivs =count;
//append content
var removeBtn = ('<a class="removeBtn">x</a>')
var h2 = ('<h2>This is div '+countDivs+'</h2>')
var appendContent = ('<div>'+h2+removeBtn+'</div>')
$('#accordion').append(appendContent);
count++;
});
//remove button
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
return false;
});
The easiest update would be to trigger a recount (or other named-event) and, upon addition or removal of an element – by clicking either the #add_item or .removeBtn – call that function using the on() method to listen for that event.
In the below code we bind the event-listener to the #accordion element, as the closest ancestor present in the DOM on page load:
$('#add_item').click(function() {
var removeBtn = ('<a class="removeBtn">x</a>');
var h2 = ('<h2></h2>');
var appendContent = ('<div>'+h2+removeBtn+'</div>');
$('#accordion').append(appendContent).trigger('recount');
});
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
// triggering the 'recount' event from the
// #accordion:
$('#accordion').trigger('recount');
return false;
});
// listening for the 'recount' event:
$('#accordion').on('recount', function(){
// looking within the #accordion for
// the <h2> elements (which contain the
// text to update), and using the text()
// method's anonymous function along with
// its i argument (the index of the current
// <h2> in the collection):
$(this).find('h2').text(function(i){
// returning the text string concatenated
// with the index plus 1 (to get a 1-based
// count, rather than JavaScript's 0-based):
return 'This is div ' + (i + 1);
});
});
$('#add_item').click(function() {
var removeBtn = ('<a class="removeBtn">x</a>');
var h2 = ('<h2></h2>');
var appendContent = ('<div>' + h2 + removeBtn + '</div>');
$('#accordion').append(appendContent).trigger('recount');
});
$(document).on('click', '.removeBtn', function() {
$(this).parent('div').andSelf().remove();
$('#accordion').trigger('recount');
return false;
});
$('#accordion').on('recount', function() {
$(this).find('h2').text(function(i) {
return 'This is div ' + (i + 1);
});
});
div {
position: relative;
}
#accordion {
margin-left: 60px;
padding: 10px;
background: #ddd;
}
#add_item {
position: absolute;
top: 20px;
left: 20px;
font-size: 20px;
padding: 5px 10px;
background: black;
color: white;
cursor: pointer;
}
.removeBtn {
font-size: 20px;
padding: 2px 10px 5px;
background: black;
color: white;
cursor: pointer;
position: absolute;
top: 0px;
font-family: verdana;
border-radius: 100%;
left: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="accordion">
</div>
<a id="add_item">+</a>
References:
on().
text().
trigger().

how to work with arrays and objects in javascript

I've got an array of cars and i'm looping through each car. I take input from the user using window.prompt() method. I take that value and filter it through my array of cars. I just want to know how I can restrict the car name the user selects to only those in the array
Fiddle : https://jsfiddle.net/qomu1fny/
var CarsWorld = {
cars : ['Honda','toyota','mercedes','jaguar'],
init: function(){
var getData = prompt('Which Car You Wanna Drive','');
for(var i = 0 ; i < this.cars.length ; i++){
$('.wrap').append(' ' + this.cars[i] + ' <br/> ');
}
},
};
CarsWorld.init();
var getData = prompt('Which Car You Wanna Drive','');
var foundCar = "";
for(var i = 0 ; i < this.cars.length ; i++){
$('.wrap').append(' ' + this.cars[i] + ' <br/> ');
//check if this car in the array is the picked car
if(this.cars[i] == getData){
foundCar = getData;
}
}
$('.wrap').append('you picked ' + foundCar);
Note that if the car isn't on the list then it won't output anything. Fiddle here: http://jsfiddle.net/e5qh3pvw/
I've tried to rephrase your question to something more understandable (currently under peer review). I understand you want to have a prompt that will restrict the choices of the user to the car models in your array.
Unfortunately, window.prompt() cannot achieve this, neither is there any synchronous (blocking) way to achieve it. You will need to use a modal dialog, and insert a regular html select element with your choices, or use a group of radio buttons.
I have created a fiddle that started getting bloated as I progressed. I used a few advanced techniques, just to engage your curiousity, since I suspect you are new to javascript.
Javascript:
var CarsWorld = {
cars : ['Honda','toyota','mercedes','jaguar'],
init: function(){
var getData = 'none';
for(var i = 0 ; i < this.cars.length ; i++){
$('.wrap').append(' ' + this.cars[i] + ' <br/> ');
}
var prompter = new CarsWorld.PromptSelect('Which Car You Wanna Drive', function(selected){
getData = selected;
alert('You chose '+ getData +'! ');
//other logic you want to apply on getData
});
prompter.show();
}
};
CarsWorld.PromptSelect = function(message, callback) {
self = this;
this.init = function(){
self.dropdown = '<select id="selectedCar">';
$.each(CarsWorld.cars, function(index, car){
self.dropdown += '<option>' + car + '</option>';
});
self.dropdown += '</select>';
self.markup = [
'<div class="prompt">',
'<div class="title">CarsWorld Prompt</div>',
'<div class="body">',
'<label for="selectedCar">'+ message +':</label>' + this.dropdown + '</div>',
'<div class="footer">',
'<button class="btn-ok">Ok</button>',
'<button class="btn-cancel">Cancel</button>',
'</div>',
'</div>'
].join('');
};
this.show = function(){
$('.overlay').show();
$('body').css('overflow', 'hidden');
self.init();
$('body').append(self.markup);
$('.prompt .btn-ok').on('click', function(){
self.hide();
callback($('#selectedCar').val());
self.destroy();
});
$('.prompt .btn-cancel').on('click', function(){
self.destroy();
});
return self;
};
this.hide = function(){
$('.prompt').hide();
$('.overlay').hide();
$('body').css('overflow', 'auto');
return self;
};
this.destroy = function(){
self.hide();
return self;
};
};
CarsWorld.init();
HTML:
<div class="wrapper">
<h1> Please choose the car of your type </h1>
<div class="wrap"></div>
<div class="overlay"></div>
</div>
CSS:
.overlay {
display: none;
position: absolute;
width: 100%;
height: 100%;
z-index: 990;
background: #444;
opacity: 0.5;
top: 0;
left: 0;
}
.prompt {
display: block;
position: absolute;
z-index: 999;
width: 300px;
height: 200px;
top: 50%;
left: 50%;
margin-left: -200px;
margin-top: -100px;
}
.prompt .title {
background: black;
color: white;
height: 10%;
padding: 10px;
border-radius: 3px 3px 0 0;
text-align: center;
font-weight: bold;
}
.prompt .body {
background: white;
height: 60%;
padding: 20px;
}
.prompt .footer {
background: grey;
text-align: right;
padding: 10px;
height: 10%;
border-radius: 0 0 3px 3px;
}

Semi-fixed text in a scrolling container

I've got a bunch of horizontal boxes containing text. The boxes are all in a horizontally scrolling container:
// generate some random data
var model = {
leftEdge: ko.observable(0)
};
model.rows = populateArray(10 + randInt(20), randRow);
ko.applyBindings(model);
$(function() {
$('.slide').on('scroll', function() {
model.leftEdge(this.scrollLeft);
})
})
function randRow() {
var events = populateArray(50 + randInt(100), randEvent);
var left = randInt(1000);
events.forEach(function(event) {
event.left = left;
left += 10 + event.width + randInt(1000);
});
return {
events: events
}
}
function randEvent() {
var word = randWord()
var width = 50 + Math.max(8 * word.length, randInt(200));
var event = {
left: 0,
width: width,
label: word
};
event.offset = ko.computed(function() {
// reposition the text to stay
// * within its container
// * fully on-screen (if possible)
var leftEdge = model.leftEdge();
return Math.max(0, Math.min(
leftEdge - event.left,
event.width - 8 * event.label.length
));
});
return event;
}
function randWord() {
var n = 2 + randInt(5);
var ret = "";
while (n-- > 0) {
ret += randElt("rmhntsk");
ret += randElt("aeiou");
}
return ret;
}
function randElt(arr) {
return arr[randInt(arr.length)];
}
function populateArray(n, populate) {
var arr = new Array(n);
for (var i = 0; i < n; i++) {
arr[i] = populate();
}
return arr;
}
function randInt(n) {
return Math.floor(Math.random() * n);
}
.slide {
max-width: 100%;
overflow: auto;
border: 5px solid black;
}
.row {
position: relative;
height: 25px;
}
.event {
position: absolute;
top: 2.5px;
border: 1px solid black;
padding: 2px;
background: #cdffff;
font-size: 14px;
font-family: monospace;
}
.event > span {
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="slide" data-bind="foreach: rows">
<div class="row" data-bind="foreach: events">
<div class="event" data-bind="style: { left: left+'px', width: width+'px' }"><span data-bind="text:label, style: { left: offset() + 'px' }"></div>
</div>
</div>
What I'd like to do is as the user scrolls from left-to-right, reposition the text within each box that partially overlaps the left border of the visible window to keep the text as visible as possible.
Currently I'm doing this by manually repositioning each item of text.
Is there a cleaner way to do this using CSS?
A friend helped me come up with this solution.
In English, the idea is to add an overlay to each row that is positioned relatively to the frame of the scrolling box, rather than the contents.
Then we can place a label for any box that overlaps the left edge in this overlay and it will appear to smoothly move as the box underneath it scrolls.
// generate some random data
var model = {
leftEdge: ko.observable(0),
};
model.rows = populateArray(10 + randInt(20), randRow);
model.width = Math.max.apply(Math, $.map(model.rows, function(row) {
return row.width
}));
ko.applyBindings(model);
$(function() {
$('.slide').on('scroll', function() {
model.leftEdge(this.scrollLeft);
})
})
function randRow() {
var events = populateArray(50 + randInt(100), randEvent);
var left = randInt(1000);
events.forEach(function(event) {
event.left = left;
left += 10 + event.width + randInt(1000);
});
return {
events: events,
width: left
}
}
function randEvent() {
var word = randWord()
var width = 50 + Math.max(8 * word.length, randInt(200));
var event = {
width: width,
label: word,
};
event.tense = ko.computed(function() {
// reposition the text to stay#
// * within its container
// * fully on-screen (if possible)
var leftEdge = model.leftEdge();
return ['future', 'present', 'past'][
(leftEdge >= event.left) +
(leftEdge > event.left + event.width - 8 * event.label.length)
];
});
return event;
}
function randWord() {
var n = 2 + randInt(5);
var ret = "";
while (n-- > 0) {
ret += randElt("rmhntsk");
ret += randElt("aeiou");
}
return ret;
}
function randElt(arr) {
return arr[randInt(arr.length)];
}
function populateArray(n, populate) {
var arr = new Array(n);
for (var i = 0; i < n; i++) {
arr[i] = populate();
}
return arr;
}
function randInt(n) {
return Math.floor(Math.random() * n);
}
.wrapper {
position: relative;
border: 5px solid black;
font-size: 14px;
font-family: monospace;
}
.slide {
max-width: 100%;
overflow: auto;
}
.slide > * {
height: 25px;
}
.overlay {
position: absolute;
width: 100%;
left: 0;
}
.overlay .past {
display: none
}
.overlay .present {
position: absolute;
z-index: 1;
top: 5.5px;
left 0;
}
.overlay .future {
display: none
}
.row {
position: relative;
}
.event {
position: absolute;
top: 2.5px;
border: 1px solid black;
padding: 2px;
background: #cdffff;
height: 14px;
}
.event .past {
float: right;
}
.event .present {
display: none;
}
.event .future {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="wrapper">
<div class="slide" data-bind="foreach: rows, style: { width: width + 'px' }">
<div class="overlay" data-bind="foreach: events">
<span data-bind="text:label, css: tense"></span>
</div>
<div class="row" data-bind="foreach: events">
<div class="event" data-bind="style: { left: left+'px', width: width+'px' }"><span data-bind="text:label, css: tense"></div>
</div>
</div></div>
This doesn't result in less javascript, but it does result in more efficient javascript, as class changes happen much less often than offset changes, so fewer updates to DOM elements are required.
You can avoid processing every "event" (in the above example) by doing some pre-partitioning of the horizontal space, and only updating events in the relevant partition.

javascript background image change using array

I am not exprienced javascript programmer so I try to play with javascript. I am trying to make a slideshow by clicking on a button. Function I am trying to make a function with array that holds the names of all the images and changing the background-image according to the index of the array. I did only this part of function yet and I cant get what is wrong.
function change(lol){
var img = ["veni1.jpg", "veni2.jpg", "veni3"];
var middle = document.getElementById("vvvmiddle");
var index = img.indexOf(middle.style.backgroundImage);
if(change === "right"){
var current = index + 1;
middle.style.backgroundImage = img[current];
}
}
middle {
width:1262px;
height:550px;
background-color: white;
margin-left: -7px;
}
#vvvmiddle {
width:700;
height:400;
background-image:url('veni1.jpg');
margin: 20px 0px 0px 310px;
float:left;
}
#sipka {
width:40;
height:40;
border-radius: 100px;
background-color: #DCDCDC;
float:right;
margin: 450px 410px 0px 0px;
}
#sipkatext {
font-family: Impact;
color: white;
font-size: 30px;
padding-left: 10px;
padding-top: 1px;
}
#sipkaurl {
text-decoration: none;
}
#sipka:hover {
background-color: #3399FF;
}
#sipka2:hover {
background-color: #3399FF;
}
#sipka2 {
width:40;
height:40;
border-radius: 100px;
background-color: #DCDCDC;
float:right;
margin: 450px -100px 0px 0px;
}
#sipkatext2 {
font-family: Impact;
color: white;
font-size: 30px;
padding-left: 13px;
padding-top: 1px;
}
<div id="middle">
<div id="vvvmiddle">
<div id="sipka" onclick="change('left')">
<div id="sipkatext">
<</div>
</div>
<div id="sipka2" onclick="change('right')">
<div id="sipkatext2">></div>
</div>
</div>
</div>
A possible solution may be this one:
var img = ["img1.png", "img2.png", "img3.png"];
var len = img.length;
var url = 'Some url...';
var current=0;
var middle = document.getElementById("vvvmiddle");
middle.style.backgroundImage = "url(" + url + img[current] + ")";
function change(dir){
if(dir == "right" && current < len-1){
current++;
middle.style.backgroundImage = "url(" + url + img[current] + ")";
} else if(dir == "left" && current > 0){
current--;
middle.style.backgroundImage = "url(" + url + img[current] + ")";
}
}
See it in action, check here jsfiddle.
You can try with that:
function change(lol) {
var img = ["veni1.jpg", "veni2.jpg", "veni3"];
var middle = document.getElementById("vvvmiddle");
var index = img.indexOf(middle.style.backgroundImage);
if(lol === "right"){
index = (index + 1) % img.length;
} else {
index = (index + img.length - 1) % img.length;
}
middle.style.backgroundImage = img[index];
}
You are checking wrong variable in condition, it should be lol, not change:
if(lol === "right"){
var current = index + 1;
middle.style.backgroundImage = img[current];
}
Also you should handle "last image" case like Nicolas suggests.

Categories

Resources