I am working with some code from BioJS of which I'd like to extend the functionality. A BioJS object forms a sequence display by creating a separate span element for each letter and creating a break after x number of letters as such (simplified):
` var j=1;
for (var i=1; i <= a.length; i++) {
if( i % opt.numCols == 0) {
str += '<span class="sequence" id="' + this.getId() + '_' + i + '">' + a[i-1] + '</span>';
str += '<br/>';
j = 1;
} else {
str += '<span class="sequence" style="'+spaceStyle+'" id="' + this.getId() + '_' + i + '">' + a[i-1];
str += ( j % opt.numColsForSpace == 0)? ' ' : '';
str += (opt.spaceBetweenChars)? ' ' : '';
str += '</span>';
j++;
}
}`
This is nice for the built-in functionality of adding highlights to specific coordinates, which just uses jQuery to find the appropriate span and change the css. I've tried to take a similar approach with hiding elements by changing them to display:none, but unfortunately this leaves the line breaks behind, and thus big holes in the text. See a picture here:
Showing/Hiding
I'd like to know if there is another way I could create a similar display that would allow me to retain the fixed-width output after hiding the elements. Ideally I would still be able to use the highlight function, but I could also re-code that as well to work in a different way.
I found the source of the problem, which was that the javascript from BioJS was adding an inline style of whitespace: pre that was preventing the span elements from wrapping within the container. It was causing the containing element to only break on line breaks.
Related
My problem is about DIV attributes in JavaScript.
DIV cannot have value attribute, but I need to make it have some "value" to hold the i variable.
Here's an example of what I have:
for (i = 1; i <= endDate; i++) {
if (i === today.getDate() && dt.getMonth() === today.getMonth() && dt.getFullYear() === today.getFullYear()) {
cells += "<div class='today'>" + i + "</div>";
} else {
cells += "<div onclick='dayChanger()' value='i'> " + i + "</div>";
}
}
function dayChanger(obj) {
dt.setDate(obj.value);
}
Well a div can have a value attribute, but it is less common. You should just use data-* attributes.
For example: <div ... data-value='i'>.
Then in your handler, you can access it like to:
obj.getAttribute("data-value")
// or, if you are not targeting dinosaur browsers:
obj.dataset.value
Also, you might consider building the div as an element instead of interpolating, but that is just personal taste. For this small example, it is fine.
PROBLEM
I've tried adding a link to the navigational tooltips and, based on html, it should be working. However, no matter which tooltip I click, I am taken to the second section - even though the address indicated is correct and should be taking me across all sections.
for (var i = 0; i < $(SECTION_SEL).length; i++) {
var link = '';
if (options.anchors.length) {
link = options.anchors[i];
}
var li = '<li><span></span>';
// Only add tooltip if needed (defined by user)
var tooltip = options.navigationTooltips[i];
if (typeof tooltip !== 'undefined' && tooltip !== '') {
li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + '' + tooltip + '</div>';
}
li += '</li>';
nav.find('ul').append(li);
}
I've tried putting the links into the init file as well, but that has the exact same effect.
Fullpage.js will ignore your link.
See line 1694
function sectionBulletHandler(e){
e.preventDefault();
var index = $(this).parent().index();
scrollPage($(SECTION_SEL).eq(index));
}
And line 567:
.on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
Please tell me solution of this problem.
I am creating 5 dynamic divs and their ids using a for loop. I want to get the the loop counter value and each of the created div's html in the format "counter: html" like 1:123. Right now I am getting only the loop counter value.
<html>
<div id="feed"></div>
</html>
<script>
for (var i = 1; i <= 5; i++) {
$('#feed').append('<div id="news' + i + '" value='
123 '/>');
var abc = $("#news" + i).attr("value");
console.log(abc);
}
</script>
Thanks in advance.
Try this.
$(document).ready(function() {
for (var i = 1; i <= 5; i++) {
$('#feed').append('<div id="news' + i + '" value="123"></div>');
//and I want to get the value of dynamic created div using this code but I am getting only the loop counter value. Please help me to get this answer.
var abc = $("#news" + i).attr('value');
console.log(abc + " : " + i);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<html>
<div id="feed"></div>
</html>
This snippet doesn't even work for me, this however, does:
for (var i = 1; i <= 5; i++) {
$('#feed').append('<div id="news' + i + '" value="123"/>');
var abc = $("#news" + i).attr("value");
console.log(abc);}
I simply changed the single quotes of value='123' to double quotes: value="123".
Don't use ids use a class
'<div id="news' + i + '" value='123'/>' should be '<div class="news">123</div>'
Use .html() not .attr("value")
for (var i = 0; i <= 4; i++) {
$('#feed').append('<div class="news">123</div>');
var abc = $('.news').eq(i).html(); // gets the html of the div with the class "news" at the index supplied by `i`, keep in mind that arrays are 0 based so 0 is the first, 1 is the second....
console.log((i+1)+':'+abc);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="feed"></div>
updating the answer as per the updated question. This code will work for you. Give it a try.
for (var i = 1; i <= 5; i++) {
$('#feed').append('<div id="news' + i + '">'+ i +': Test</div>');
}
But I tell you again not to use the value tag, you already have your counter in id so split it fro there if you want.
Cheers!!
You're using id's. You can't use an id on multiple divs, so you need to use class.
Not quite sure what you want, and div tag not supposed have value attribute, if you want to add your defined attribute use data-my_attribute instead. In your code, everything is ok except for this code :
Change this :
$('#feed').append('<div id="news' + i + '" value='123'></div>');
into this :
$('#feed').append('<div id="news' + i + '" value="123"></div>');
I have a method called refreshHistory() that basically reads locally stored list of json (using https://github.com/marcuswestin/store.js/) and populates a list in the order they were stored at.
Everytime a user action happens, this method is called. But as the list gets bigger and bigger, it slows down the browser to a crawl.
function refreshHistory() {
var records = typeof store.get('history') == "undefined" ? 0 : store.get('history').history;
;
if (records == 0) {
$('#content #historyView').html('<i>history show up here in order.</i>');
} else {
var xhistory = '<div id="history">';
for (var i = 0; i < records.length; i++) {
var xaction = records[i]
xhistory += '<div id="action">' + (i + 1) + '. ' + '<b>' + xaction.action + "</b> " + xaction.caption + '<span class="delaction" id=' + i + ' data-stamp="' + xaction.msg + '" style="color:red;cursor:pointer;">' + '[remove]' + '</span></div>'
}
xhistory += "</div>"
$('#qtip-0-content #historyView').html(xhistory);
}
}
Rendering everything on every event is a simple strategy, which is good, but it does run into the performance problems you are describing. It's hard to give specific advice, but you could either:
Implement a more detailed rendering logic, where only new items are rendered and added to the DOM.
Use ReactJs or Virtual DOM libraries, which allow your code to use the render everything pattern, but make the actual updates to the DOM faster by doing the minimum needed.
The only way to really make this efficient is to implement it in a different way.
I've been using knockout.js personally and am very happy with it. Basically you write a template and the library handles the DOM node changes, only updating the parts needed. You will need to learn how to think slightly differently, but there are some great tutorials available.
That said, one simple trick you can try is move the selectors outside the function so they are only ran once instead of each time you call the function.
For sanity I would also keep records variable the same type whether or not the .get('history') returns undefined.
var contentHistoryView = $('#content #historyView');
var qtipHistoryView = $('#qtip-0-content #historyView');
function refreshHistory() {
var records = typeof store.get('history') == "undefined" ? [] : store.get('history').history;
if (records.length) {
contentHistoryView.html('<i>history show up here in order.</i>');
} else {
var xhistory = '<div id="history">';
for (var i = 0; i < records.length; i++) {
var xaction = records[i]
xhistory += '<div id="action">' + (i + 1) + '. ' + '<b>' + xaction.action + "</b> " + xaction.caption + '<span class="delaction" id=' + i + ' data-stamp="' + xaction.msg + '" style="color:red;cursor:pointer;">' + '[remove]' + '</span></div>'
}
xhistory += "</div>"
qtipHistoryView.html(xhistory);
}
}
I doubt this will have a huge impact though, as I suspect most of the execution time is spent in the loop.
Hit a slight bump on something.
So I have a spreadsheet feed coming through via json.
Once they are loaded, if they contain a certain word, I want an elment that is already on the page to do something.
Having some trouble.
Here is my code:
/*feed*/
function displayContent(json) {
var len = json.feed.entry.length
var divtag = ''
for (var i=0; i<len; i++) {
divtag += [
'<div id=' +' tooltipwrap' + i + '>' +
'<span style="font-size:22px; font-weight:600;">',
json.feed.entry[i].gsx$studentname.$t + ' ' +
'<span class="hide" style="font-size:18px; font-weight:300;">',
json.feed.entry[i].gsx$classlevel.$t
+ '</span>' + '<span id=' + 'tooltipside' + i +'>' +
json.feed.entry[i].gsx$gender.$t + '-' +
'</span>',
'</div>'
].join('');
}
document.getElementById('tipswrap').innerHTML = divtag
}
/* what I wanted to do */
if ($('#tooltipside0').html() === "Senior") {
$("#test1").addClass('no');
}
Here is the JSFiddle
Pay attention to the tabulation. Right now your code is hard to read because you have failed to do so.
Here:
var len = json.feed.entry.length
var divtag = ''
you are missing semi-colons. You have to put semi-colon at the end of any operation, like this:
var len = json.feed.entry.length;
var divtag = '';
Semi-colons serve as operation separators.
Here:
divtag += [
'' +
'',
json.feed.entry[i].gsx$studentname.$t + ' ' +
'',
json.feed.entry[i].gsx$classlevel.$t
+ '' + '' +
json.feed.entry[i].gsx$gender.$t + '-' +
'',
'</div>'
].join('');
You have multiple problems:
You have failed to put your html attributes into quotes, so the resulting html will be invalid. Also, you have used comma instead of plus at the last concatenation.
CONCLUSION: You are obviously not ready to implement this code, because:
- You lack Javascript syntax knowledge
- You lack HTML syntax knowledge
- You do not pay attention to tabulation
As a consequence, your main problem is not what the question states, namely, how to add a class to an element depending on JSON feed. Your main problem is that you lack Javascript and HTML education. Please, follow some tutorials to be able to solve a problem and after that try again to solve your problem. If you fail to do so, then you will have at least an educated guess.
After adding the content to tipswrap add the condition
document.getElementById('tipswrap').innerHTML = divtag; //$('#tipswrap').html(divtag)
if ($.trim($('#tooltipside0').html()) === "Senior") {
$("#test1").addClass('no');
}
Demo: Fiddle
I recommend you add a class to all of your rows called student and then from there use this javascript:
function displayContent(json) {
var len = json.feed.entry.length
var divtag = ''
for (var i = 0; i < len; i++) {
divtag +=
'<div class="student" id="tooltipwrap'+i+'">'+
'<span style="font-size:22px; font-weight:600;">'+
json.feed.entry[i].gsx$studentname.$t +
'<span class="hide" style="font-size:18px; font-weight:300;">'+
json.feed.entry[i].gsx$classlevel.$t +
'</span> '+
'<span id="tooltipside'+i+'">'+
json.feed.entry[i].gsx$gender.$t + '-' +
'</span>'+
'</span>'+
'</div>';
}
document.getElementById('tipswrap').innerHTML = divtag
}
jQuery(document).ready(function($) {
$('.student').each(function() {
if ($(this).text().toLowerCase().indexOf("senior") >= 0)
$(this).addClass('senior');
});
});
Here's a demo