I want in a tablerow to have a label with a day's name. this mean that i dont know the actual width of the label, and that label.toImage().width does not return the actual size even after postlayout event. And also i want to have horizontally aligned a scrollview with a random text, sometimes very big. What i have is:
var storehoursscrollingmessagestyle = {
left:"10dp",
font:{fontSize:'18dp',fontWeight:"bold"}
};
var storehoursscrollviewstyle = {
contentWidth: 'auto',
contentHeight: 'auto',
height: '70dp',
width:Ti.UI.FILL,
scrollType: 'horizontal'
};
var storehoursrowstylegray={
classNane:"storeoptions",
selectedBackgroundColor:"#E8E8E8",
backgroundColor:"#E8E8E8",
height:"70dp"};
var storehoursrowlabelstyle={
left:"10dp",
height:"70dp",
font:{fontSize:'18dp',fontWeight:"bold"},
color:"Black"
};
var storehoursviewrowstyle ={
width:'200dp',
height:'70dp',
layout:'horizontal'
};
var storehoursbuttontitleview = Titanium.UI.createLabel(storehoursrowlabelstyle);
storehoursbuttontitleview.text = dayMappings[today] + " " + openTimeFormatted + " - " + closeTimeFormatted;
storehoursbuttonview.add(storehoursbuttontitleview);
var view = Ti.UI.createView(storehoursviewrowstyle);
var scrollview = Ti.UI.createScrollView(storehoursscrollviewstyle);
scrollview.add(storehoursscrollingmessagetitleview);
view.add(storehoursbuttontitleview);
var subviewviewforscrollview = Ti.UI.createView(storehoursviewrowstyle);
subviewviewforscrollview.add(scrollview);
view.add(subviewviewforscrollview);
storehoursbuttonview.add(view);
if i set width:'30%' to storehoursscrollviewstyle the horizontal layout will be shown as it should but if i set 100% the scrolling view disappears.
So my question is how to have a label and a scrollingview inside a table row, without knowing their sizes and without setting a hardcoded width value for each other.
I did it by adding postlayout event to my label, also removed horizontal layout from view and hardcoded widths.
function storehoursbuttontitleview_postlayout(e) {
if (e.source.set == null) {
var storehoursscrollingmessagetitleview = Titanium.UI.createLabel(storehoursscrollingmessagestyle);
storehoursscrollingmessagetitleview.text = e.source.closedMessage;
var view = Ti.UI.createView(storehoursviewrowstyle);
view.left = e.source.size.width + 20 + "dp";
var scrollview = Ti.UI.createScrollView(storehoursscrollviewstyle);
view.add(scrollview);
if (Titanium.Platform.name != 'android') {
var str = e.source.closedMessage;
var chunks = [];
for (var i = 0, charsLength = str.length; i < charsLength; i += 100) {
chunks.push(str.substring(i, i + 100));
}
var finalwidth = 0;
for (i=0; i<chunks.length; i++) {
var storehoursscrollingmessagetitleviewtemp = Titanium.UI.createLabel(storehoursscrollingmessagestyle);
storehoursscrollingmessagetitleviewtemp.text = chunks[i];
finalwidth = finalwidth + storehoursscrollingmessagetitleviewtemp.toImage().width;
}
var labelInsideScrollWidth = finalwidth;
storehoursscrollingmessagetitleview.width = finalwidth + 10 + "dp";
scrollview.add(storehoursscrollingmessagetitleview);
}
else {
scrollview.add(storehoursscrollingmessagetitleview);
}
e.source.row.add(view);
e.source.set = true;
}
}
Related
I'm struggling to make this idea of mine work..
The idea is to auto-scroll the dynamically filled unsorted list.
This is how I've build the Unsorted List with List Items in JavaScript
$.getJSON(sportlink_url + 'programma?gebruiklokaleteamgegevens=NEE&aantaldagen=' + programma_dagen + '&eigenwedstrijden=JA&thuis=JA&uit=JA&' + sportlink_clientID, function (uitslag) {
for (let i = 0; i < Object.keys(uitslag).length; i++) {
//for (let i = 0; i < 1; i++) {
var aanvangstijd = uitslag[i].aanvangstijd;
var thuisteam = uitslag[i].thuisteam;
var uitteam = uitslag[i].uitteam;
var accommodatie = uitslag[i].accommodatie;
var competitiesoort = uitslag[i].competitiesoort;
var datumNumber = uitslag[i].datum.substring(0,2);
var datumMonth = uitslag[i].datum.slice(-4);
var datumMonthClean = datumMonth.substring(0,3);
//Fetch the DIV
var el = document.getElementById("match_program");
//Create new list item
var node = document.createElement("li");
node.setAttribute('role', 'presentation');
//Create ticketDiv
var ticketDiv = document.createElement("div");
ticketDiv.setAttribute('class', 'tg-ticket');
//Create timeBox
var timeBox = document.createElement("time");
timeBox.setAttribute('class', 'tg-matchdate');
timeBox.innerHTML = (datumNumber + " <span>" + datumMonthClean + "</span>");
//Create matchdetail
var matchDetail = document.createElement("div");
matchDetail.setAttribute('class', 'tg-matchdetail');
matchDetail.innerHTML = ("<h4>" + thuisteam + "<span> - </span>" + uitteam + " | " + aanvangstijd + ", " + accommodatie);
//Create themeTag
var themeTag = document.createElement("span");
themeTag.setAttribute('class', 'tg-theme-tag');
themeTag.innerHTML = (competitiesoort);
//Build the hole thing
ticketDiv.appendChild(timeBox);
matchDetail.appendChild(themeTag);
ticketDiv.appendChild(matchDetail)
node.appendChild(ticketDiv);
el.appendChild(node);
This is the Unsorted List in HTML
<ul id="match_program" class="tg-tickets tg-tabnav" role="tablist" data-autoscroll="">
</ul>
This is the function i'm currently using for auto-scroll, but it has .ulContent').height() > $('.ulContainer').height() and because my ulContent doesn't have a prefix height in CSS it's not going to work..
And I can't put a height prefix in CSS for the ulContent cause I don't know on forehand if it's going to be 500px of 800px, the unsorted list is being filled from a JSON string.
$(document).ready(function() {
if($('.ulContent').height() > $('.ulContainer').height()) {
setInterval(function () {
start();
}, 3000);
}
});
function animateContent(direction) {
var animationOffset = $('.ulContainer').height() - $('.ulContent').height();
if(direction == 'up') {
animationOffset = 0;
}
}
The animatie function is being called at the bottom of the HTML file just before the closing tags of the body
I manged to figure it out;
var amountGames = Object.keys(uitslag).length
var calulContent = amountGames * 116 + 500;
var setulContent = calulContent + "px";
document.getElementById('ulContent').style.height= setulContent;
That way the ulContent is always filled and the container uses a fixed number of 500px;
I am new to javascript and trying to learn from the beginning.
I have a script where I can do two different calculations using radio buttons, area and circumference.
I want to display how many times people have counted out different calculations.
If I use to show clicks on button then it counts everything together, but how can I separate them?
document.getElementById("calculate").addEventListener("click", function() {
var button = document.getElementById("calculate");
var x, text;
x = document.getElementById("radius").value;
if (document.getElementById("area").checked) {
if (isNaN(x) || x < 1 || x > 100) {
text = "Fel radie";
document.getElementById('radius').value = '';
} else {
let radius = document.getElementById("radius").value;
area = Math.PI * radius * radius;
}
if (document.getElementById("areaoutput").innerHTML = text);
else(document.getElementById("areaoutput").innerHTML = "Area = " + area);
}
if (document.getElementById("circumference").checked) {
let radius = document.getElementById("radius").value;
if (isNaN(x) || x < 1 || x > 100) {
text = "Fel radie";
document.getElementById('radius').value = '';
} else {
let radius = document.getElementById("radius").value;
circumference = Math.PI * 2 * radius;
}
if (document.getElementById("circoutput").innerHTML = text);
else(document.getElementById("circoutput").innerHTML = "Circumference = " + circumference);
}
if (document.getElementById("area").checked) {
var count = localStorage.on_load_counter || 0;
var button = document.getElementById("calculate");
var display = document.getElementById("areacount");
button.onclick = function() {
localStorage.on_load_counter = display.innerHTML = ++count;
}
}
if (document.getElementById("circumference").checked) {
var count = localStorage.on_load_counter || 0;
var button = document.getElementById("calculate");
var display = document.getElementById("circcount");
}
button.onclick = function() {
localStorage.on_load_counter = display.innerHTML = ++count;
}
}, false);
Try doing something like this
var combinationsDone = [];
Then every time the user does a calculation, you would add an object to combinationsDone.
For example, if they have a radius of 5, and circumference isn't checked, this is what you should do.
var combination = {
radius: 5,
circumference: false
}
if(!combinationsDone.includes(combination)){
combinationsDone.push(combination);
}
What this does is it makes sure that the combination wasn't recorded previously before adding the combination. Then, when you want to get the number of different combinations they have done, just user combinationsDone.length.
You can use a global variable. which is increased every time you call the function.
var myFuncCalls = 0;
function myFunction()
{
myFuncCalls++;
alert( "I have been called " + myFuncCalls + " times" );
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Background: I am working on a dashboard, which shows a header and a table underneath. The table can have many rows (over 100).
Problem: large number of rows triggers a vertical scrollbar to show up, which hides the rest of the rows.
Possible solution: I would like to rotate, what table rows are showed on every screen the dashboard is on. I would like to avoid to set a fixed number of rows that are visible on screen and instead, determine how many rows can be put on the screen before the scroll bar shows up. This means that, first, I would like to determine how many rows are visible on the screen before the scrollbar shows up, and then create a carousel animation, where the next X rows are showed until all the rows are showed and the animation resets.
Technologies used: React JS, Bootstrap table
For the carousel part, I found Bootstrap Carousel to work fine, but the problem is figuring out, how many rows are visible on the screen. How do I determine, how many rows I can display on the screen before the scroll-bar shows up? Thank you very much!
One possible solution would be:
Create an element in the DOM which would be 100% height (any other possible height will work too). For example:
<div id="row-wrapper" style="height: 100%"></div>
Get the height of the element.
var availableHeight = document.getElementById('row-wrapper').clientHeight;
Knowing how much height your single row occupies just divide availableHeight and you will know how many rows to render. In case your row height is 30:
var numberOfRows = Math.floor(availableHeight / 30);
I know you tagged ReactJS, but a good basis is to always keep your DOM as small as possible. My tactic would be to keep the data in JavaScript and only introduce to the DOM what is absolutely needed.
Below is a simple example showing 10 rows with an offset:
var dummyData = [];
(function populateData() {
var names = ["Greg", "Jeff", "Bob", "Bruce", "Clark", "Diana"];
while (dummyData.length < 100000) {
dummyData.push({
name: names[Math.floor(Math.random() * names.length)],
age: Math.floor(Math.random() * 100)
});
}
})();
function displayData(data, offset, limit) {
if (offset === void 0) {
offset = 0;
}
if (limit === void 0) {
limit = data.length;
}
var tbody = document.body.appendChild(document.createElement("tbody"));
for (var i = offset; i < (limit + offset); i++) {
if (i >= data.length) {
break;
}
var person = data[i];
var tr = tbody.appendChild(document.createElement("tr"));
tr.innerHTML = "<td>" + i + "</td><td>" + person.name + "</td><td>" + person.age + "</td>";
}
return tbody;
}
var pagesize = 10;
var offset = 0;
var offsetInput = document.body.appendChild(document.createElement("input"));
offsetInput.type = "number";
offsetInput.min = "0";
offsetInput.value = "0";
var table = document.body.appendChild(document.createElement("table"));
table.style.width = "100%";
table.innerHTML = "<thead><tr><th>Index</th><th>Name</th><th>Age</th></tr></thead>";
var tbody = table.appendChild(displayData(dummyData, offset, pagesize));
function update() {
if (offsetInput.validity.valid) {
offset = parseInt(offsetInput.value, 10);
table.removeChild(tbody);
tbody = displayData(dummyData, offset, pagesize);
table.appendChild(tbody);
}
}
offsetInput.addEventListener("change", update);
offsetInput.addEventListener("keyup", update);
From here it would be a matter of some CSS tricking and reading the scrollbar to get an offset.
var dummyData = [];
(function populateData() {
var names = ["Greg", "Jeff", "Bob", "Bruce", "Clark", "Diana"];
while (dummyData.length < 100) {
dummyData.push({
name: names[Math.floor(Math.random() * names.length)],
age: Math.floor(Math.random() * 100)
});
}
})();
function displayData(data, offset, limit) {
if (offset === void 0) {
offset = 0;
}
if (limit === void 0) {
limit = data.length;
}
var tbody = document.body.appendChild(document.createElement("tbody"));
for (var i = offset; i < (limit + offset); i++) {
if (i >= data.length) {
break;
}
var person = data[i];
var tr = tbody.appendChild(document.createElement("tr"));
tr.innerHTML = "<td>" + i + "</td><td>" + person.name + "</td><td>" + person.age + "</td>";
}
return tbody;
}
var pagesize = 10;
var offset = 0;
var offsetInput = document.body.appendChild(document.createElement("input"));
offsetInput.type = "number";
offsetInput.min = "0";
offsetInput.max = "" + (dummyData.length - pagesize);
offsetInput.value = "0";
var outerContainer = document.body.appendChild(document.createElement("div"));
outerContainer.style.maxHeight = "400px";
outerContainer.style.width = "450px";
outerContainer.style.overflowY = "scroll";
var innerContainer = outerContainer.appendChild(document.createElement("div"));
innerContainer.style.height = dummyData.length * 20 + 200 + "px";
var table = innerContainer.appendChild(document.createElement("table"));
table.style.position = "absolute";
table.style.width = "400px";
table.innerHTML = "<thead><tr><th>Index</th><th>Name</th><th>Age</th></tr></thead>";
var tbody = table.appendChild(displayData(dummyData, offset, pagesize));
var handle;
function update() {
table.removeChild(tbody);
tbody = displayData(dummyData, offset, pagesize);
table.appendChild(tbody);
clearTimeout(handle);
handle = setTimeout(function() {
offsetInput.value = offset.toString();
outerContainer.scrollTop = offset * 20;
}, 100);
}
function updateInput() {
if (offsetInput.validity.valid) {
offset = parseInt(offsetInput.value, 10);
}
update();
}
function updateScroll() {
offset = Math.floor(outerContainer.scrollTop / 20);
update();
}
outerContainer.addEventListener("scroll", updateScroll);
offsetInput.addEventListener("change", updateInput);
offsetInput.addEventListener("keyup", updateInput);
This is an example how you can fill a div until its full. Made a jQuery answer too if someone is interested in that.
I made 2 div's. One with a set height(100% in the example but can be static height too) and inside a growable div that grows with the content.
First it will fill the growable div as long it is smaller then the content div.
The last added element could be bigger then the remaining space. If that happens it removes the last element.
This also works with content with dynamic heights.
Note: When using while loops it's always good to have a backup plan to avoid infinite loops. Therefore I added a max records variable.
Javascript:
window.onload = function() {
document.getElementById('fill').onclick = function() {
var content = document.getElementById('content');
var growableWrapper = document.getElementById('growableWrapper');
var maxRecords = 50;
while ((content.childNodes.length === 0 || parseInt(window.getComputedStyle(growableWrapper).height) < parseInt(window.getComputedStyle(content).height)) && growableWrapper.childNodes.length < maxRecords) {
var newElement = document.createElement("p");
var newText = document.createTextNode("Test");
newElement.appendChild(newText);
growableWrapper.appendChild(newElement);
}
if (window.getComputedStyle(growableWrapper).height > window.getComputedStyle(content).height && growableWrapper.childNodes.length > 1) {
growableWrapper.removeChild(growableWrapper.childNodes[growableWrapper.childNodes.length - 1]);
}
}
}
html,
body,
#content {
margin: 0;
padding: 0;
height: 100%;
}
#fill,
#content {
width: 40%;
float: left;
}
#content {
background-color: gray;
overflow: hidden;
}
#growableWrapper {
background-color: lightgray;
overflow: auto;
}
<div>
<button id="fill">Fill</button>
</div>
<div id="content">
<div id="growableWrapper">
</div>
</div>
jQuery:
$(document).ready(function() {
$('#fill').on('click', function() {
var content = $('#content');
var growableWrapper = $('#growableWrapper');
var maxRecords = 50;
while ((content.children().length === 0 || growableWrapper.height() < content.height()) && growableWrapper.children().length < maxRecords) {
growableWrapper.append('<p>test</p>');
}
if(growableWrapper.height() > content.height() && growableWrapper.children().length > 1) {
growableWrapper.children().last().remove();
}
});
});
html,
body,
#content {
margin: 0;
padding: 0;
height: 100%;
}
#fill, #content {
width: 40%;
float: left;
}
#content {
background-color: gray;
overflow: hidden;
}
#growableWrapper {
background-color: lightgray;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<button id="fill">Fill</button>
</div>
<div id="content">
<div id="growableWrapper">
</div>
</div>
Hi i am trying to display list on mouse over if length is >0 then i am displaying count.On mouse over list i want to display list.But in my case list is always displaying when length is >o.How to display list only on mouse over?
what exactly i am trying is
if (feature.attributes.hasOwnProperty("ExceptionType")) {
var exceptionType = 'x,y';
if (exceptionType)
{ var activeExceptions = exceptionType.split(','); }
else
{ var activeExceptions = []; }
var item, items = [];
for (var i = 0; i < activeExceptions.length; i++) {
item = {};
item.activeexception = activeExceptions[i];
items.push(item);
}
var main = $("<ul>");
var str = "<ul>";
for (var i = 0; i < items.length; i++) {
str += "<li>" + items[i].activeexception + "</li>";
}
$('[rel="tooltip"]').tooltip();
main.html(str);
if (activeExceptions.length == 0) {
feature.attributes.Hoverlist = ".showme{display: none}";
feature.attributes.ShowExceptionType = "display:none";
}
else
feature.attributes.Hoverlist = ".showhim:hover .showme{ display : block;}";
feature.attributes.ShowExceptionType = "display:block";
feature.attributes.HoverContent = str;
feature.attributes.ExceptionCount = activeExceptions.length;
}
"description": "<div class='showhim' style='{ShowExceptionType}' ng-mouseover='alert('hi');'>{ExceptionCount}<div class='showme' style='{Hoverlist}'>{HoverContent}</div></div>",
The problem is i need to put my tooltip on top when popup loads.
$('[rel="tooltip"]').tooltip();
I am trying to render the list based on virtual rendering concept. I am facing some minor issues, but they are not blocking the behaviour. Here is the working fiddle http://jsfiddle.net/53N36/9/ and Here are my problems
Last items are not visible, I assume some where I missed indexing.(Fixed, Please see the edit)
How to calculate scrollPosition if I want to add custom scroll to this.
Is this the best method or any other?
I have tested it with 700000 items and 70 items in chrome. Below is the code
(function () {
var list = (function () {
var temp = [];
for (var i = 0, l = 70; i < l; i++) {
temp.push("list-item-" + (i + 1));
}
return temp;
}());
function listItem(text, id) {
var _div = document.createElement('div');
_div.innerHTML = text;
_div.className = "listItem";
_div.id = id;
return _div;
}
var listHold = document.getElementById('listHolder'),
ht = listHold.clientHeight,
wt = listHold.clientWidth,
ele = listItem(list[0], 'item0'),
frag = document.createDocumentFragment();
listHold.appendChild(ele);
var ht_ele = ele.clientHeight,
filled = ht_ele,
filledIn = [0];
for (var i = 1, l = list.length; i < l; i++) {
if (filled + ht_ele < ht) {
filled += ht_ele;
ele = listItem(list[i], 'item' + i);
frag.appendChild(ele);
} else {
filledIn.push(i);
break;
}
}
listHold.appendChild(frag.cloneNode(true));
var elements = document.querySelectorAll('#listHolder .listItem');
function MouseWheelHandler(e) {
var e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
console.log(delta);
//if(filledIn[0] != 0 && filledIn[0] != list.length){
if (delta == -1) {
var start = filledIn[0] + 1,
end = filledIn[1] + 1,
counter = 0;
if (list[start] && list[end]) {
for (var i = filledIn[0]; i < filledIn[1]; i++) {
if (list[i]) {
(function (a) {
elements[counter].innerHTML = list[a];
}(i));
counter++;
}
}
filledIn[0] = start;
filledIn[1] = end;
}
} else {
var start = filledIn[0] - 1,
end = filledIn[1] - 1,
counter = 0;
if (list[start] && list[end]) {
for (var i = start; i < end; i++) {
if (list[i]) {
(function (a) {
elements[counter].innerHTML = list[a];
}(i));
counter++;
}
}
filledIn[0] = start;
filledIn[1] = end;
}
}
//}
}
if (listHold.addEventListener) {
listHold.addEventListener("mousewheel", MouseWheelHandler, false);
listHold.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
} else listHold.attachEvent("onmousewheel", MouseWheelHandler);
}());
Please suggest me on this.
EDIT:
I have tried again and I am able to fix the indexing issue. http://jsfiddle.net/53N36/26/
But how can I calculate the scroll position based on the array list currently displayed.
Is this the best method or any other?
I think something that would make this much easier is not to try to handle scrolling yourself.
In this fiddle I show that you can let the browser handle scrolling for you, even though we are using virtual rendering.
Using .scrollTop I detect where the browser thinks the user is looking, and I draw in items based on that.
You'll note that if you set hidescrollbar to false and the user uses it to scroll, my method still runs fine.
Therefore, to calculate scroll position you can just use .scrollTop.
And as for custom scrolling, just make sure you influence the .scrollTop of #listHolder and recall refreshWindow()
CODE FROM FIDDLE
(function () {
//CHANGE THESE IF YOU WANT
var hidescrollbar = false;
var numberofitems = 700000;
//
var holder = document.getElementById('listHolder');
var view = null;
//get the height of a single item
var itemHeight = (function() {
//generate a fake item
var div = document.createElement('div');
div.className = 'listItem';
div.innerHTML = 'testing height';
holder.appendChild(div);
//get its height and remove it
var output = div.offsetHeight;
holder.removeChild(div);
return output;
})();
//faster to instantiate empty-celled array
var items = Array(numberofitems);
//fill it in with data
for (var index = 0; index < items.length; ++index)
items[index] = 'item-' + index;
//displays a suitable number of items
function refreshWindow() {
//remove old view
if (view != null)
holder.removeChild(view);
//create new view
view = holder.appendChild(document.createElement('div'));
var firstItem = Math.floor(holder.scrollTop / itemHeight);
var lastItem = firstItem + Math.ceil(holder.offsetHeight / itemHeight) + 1;
if (lastItem + 1 >= items.length)
lastItem = items.length - 1;
//position view in users face
view.id = 'view';
view.style.top = (firstItem * itemHeight) + 'px';
var div;
//add the items
for (var index = firstItem; index <= lastItem; ++index) {
div = document.createElement('div');
div.innerHTML = items[index];
div.className = "listItem";
view.appendChild(div);
}
console.log('viewing items ' + firstItem + ' to ' + lastItem);
}
refreshWindow();
document.getElementById('heightForcer').style.height = (items.length * itemHeight) + 'px';
if (hidescrollbar) {
//work around for non-chrome browsers, hides the scrollbar
holder.style.width = (holder.offsetWidth * 2 - view.offsetWidth) + 'px';
}
function delayingHandler() {
//wait for the scroll to finish
setTimeout(refreshWindow, 10);
}
if (holder.addEventListener)
holder.addEventListener("scroll", delayingHandler, false);
else
holder.attachEvent("onscroll", delayingHandler);
}());
<div id="listHolder">
<div id="heightForcer"></div>
</div>
html, body {
width:100%;
height:100%;
padding:0;
margin:0
}
body{
overflow:hidden;
}
.listItem {
border:1px solid gray;
padding:0 5px;
width: margin : 1px 0px;
}
#listHolder {
position:relative;
height:100%;
width:100%;
background-color:#CCC;
box-sizing:border-box;
overflow:auto;
}
/*chrome only
#listHolder::-webkit-scrollbar{
display:none;
}*/
#view{
position:absolute;
width:100%;
}