Compress HTML - Elements? - javascript

I have dropdown-Lists which have a lot of elements (>1000). When I select one of those elements the dropdown has to be rebuild because the selection of one element can cause others to disappear. I solve this in code behind (asp.net). Showing and hiding that dropdown usually is done in several milliseconds.
But when I select an element the div has to be rebuild which takes up to 20 seconds which is no surprise as that div contains about 300KB of Data which have to be sent to the client. The DIV looks like this:
<div id="ctl00_PlaceHolderMain_ctlProductSelector_SubstancesList" class="substancesListWrapper">
<ul>
<li class='elementSingle'>(2-Propyloxy)ethyl acetate</li>
<li class='elementSingle'>[(2-Propenyloxy)methyl] oxirane</li>
<li class='elementSingle'>1-(2-Pyridyl) piperazine</li>
<li class='elementSingle'>1,1,1,2-Tetrachloro-2,2-difluoroethane</li>
<li class='elementSingle'>1,1,1,2-Tetrafluoroethane</li>
<li class='elementSingle'>1,1,1-Trichloroethane</li>
(etc.)
Now I wonder if there is a way to compress that div-String and decompress it client-side by jQuery or something like that to reduce traffic. Does that work and if yes: What percentage of bytes do I usually safe?
This all happens in a SharePoint-Site (which should not make any difference hopefully)

You might improve several things.
One would be to move all your JavaScript links into one.
This would save you 85 characters per row.
<li class='elementSingle'>(2-Propyloxy)ethyl acetate</li>
<li class='elementSingle'>[(2-Propenyloxy)methyl] oxirane</li>
Could become this
<li class='elementSingle'><a href='#3268'>(2-Propyloxy)ethyl acetate</a></li>
<li class='elementSingle'><a href='#2415'>[(2-Propenyloxy)methyl] oxirane</a></li>
...
And one jquery click handler:
jQuery("li.elementSingle a").click(function(){
__doPostBack('ctl00_PlaceHolderMain_ctlProductSelector_pnlSubstances', this.href.replace('#',''));
});
Another point would be to remove class='elementSingle' and add a id to your ul for css/js.
This would save 22 characters per row.

If you're using jQuery already, just remove the anchors completely and provide id attributes for the list item elements.
The use a jQuery selector that reads out the id.
HTML would look kinda like this...
<div id="ctl00_PlaceHolderMain_ctlProductSelector_SubstancesList" class="substancesListWrapper">
<ul>
<li class='elementSingle' id="ct100-3268">(2-Propyloxy)ethyl acetate</li>
<li class='elementSingle' id="ct100-2415">[(2-Propenyloxy)methyl] oxirane</li>
etc...
The jQuery could be something like this...
$(function() {
$('#ctl00_PlaceHolderMain_ctlProductSelector_SubstancesList .elementSingle')
.click(function() {
var number = $(this).attr('id').match(/-(\d+)$/)[1];
__doPostBack('ctl00_PlaceHolderMain_ctlProductSelector_pnlSubstances', number);
});
});
(disclaimer; above is untested, but should give you a decent indication. Post a jsfiddle example first if you want a tested example).
Alternatively, think about using AJAX to load the list after loading the rest of the page.

Related

Html change div content

I'm having a struggle. It's not one of these questions how to do it but more like how to do that better.
What im trying to achieve
Also I want to load rest into content when clicking on nav's
My question is what's "proper" or correct approach to do it without making a mess in a code.
How I done it so far
<li><a class="navelement" data-url="resources/web/loadit.html" href="#">navbar A</a></li>
And used jquery
$(document).ready(function(){
$('.navelement').click(function(e){
e.preventDefault;
$('#content').load($(this).data('url'));
});
$('.navelement:eq(0)').click();
});
I like this approach but I need to execute ajax rest call each time I change navbar.
Second approach I can think off is to hide/show in css div's. Any tip will be appreaciated.
Both of your approaches are correct but decision making points would be how frequently the data in div is changed and how much bandwidth will it cost to keep all divs loaded with data.
If data in div is frequently changed then I would suggest to use approach 2, i.e. load all divs once and hide and show the required one. This will improve the performance as ajax calls over network has time latency. Using approach 2 in this case will improve UI experience. This is also called as eager loading.
But in case if you have heavy data and user need not require all the data you have loaded then it will cause unnecessary loading of all divs which could consume considerable bandwidth and also cause long initial loading of page. In this case approach 1 is recommended. This is called as lazy loading.
What I suggest to you is , first load all your html nav in the content and hide them (adding class) , also set foreach generated div a custom class (by example I added the index of nav element ) , with this you'll prevent multiple ajax loading ( only once ).
then , after clicking on each nav just show it's content by refering to the generated class by example (nav1 ,nav2, nav 3)
Please find bellow a working snippet
$(function() {
$(".navelement").each(function(index, elm) {
if ($(elm).data("url")) {
var navElment = $("<div class='navdiv nav" + index + " hidden'>").load($(elm).data("url"));
$("#content").append(navElment);
$(elm).on("click", function() {
$(".navdiv").addClass("hidden");
$(".navdiv.nav" + index).removeClass("hidden");
})
}
})
})
.hidden {
display: none;
}
ul li {
display: inline;
padding:5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><a class="navelement" data-url="https://httpbin.org/get?text=navAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" href="#">navbar A</a></li>
<li><a class="navelement" data-url="https://httpbin.org/get?text=navBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" href="#">navbar B</a></li>
<li><a class="navelement" data-url="https://httpbin.org/get?text=navCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" href="#">navbar C</a></li>
</ul>
<div id="content">
</div>

A function with changing variable, dependent on a class

So, first some background.
I have 9 types of rooms that are displayed as thumbnails with the name. What I want to do is that on click "Additional Information" - the rooms with disappear and the expanded version of a chosen room type will appear with the description and bigger picture. Also, there is an ability to go next and previous in the expanded view. I do not have a problem with this expansion and previous/next. BUT!
Here is what I am trying to achieve: if the code looks approximately like
<ul id="room_holder">
<li><div class="room 1">Additional Info</div></li>
<li><div class="room 2">Additional Info</div></li>
and so on...
And the expandable area will look something like:
<div id="expandable">
<div id="picture">Blah-blah-blah, some description, etc</div>
</div>
So, basically, what I can't figure out is how to get the needed slide to show when the correspondint thumbnail is pressed. I know I can do the .addClass method, and copy the code 9 times, for each of the numbers (1-9). But I believe it is 9 times more compact if I have some sort of function, that gets the second class name (the number) by using .split(' ')[1] and then using it as part of the variable in the part which opens the corresponding expandable view. So, my question is: how do I do this? I am a newbie with javascript, but try to learn on the go!
Oh, and the codepen that I've been trying to deal with is:
http://codepen.io/godban/pen/QbZmxz
Firstly, you should use data-* attribute instead of classes (new in HTML5) data attributes, w3school :
<ul id="room_holder">
<li><div class="room" data-room="1">Additional Info</div></li>
<li><div class="room" data-room="2">Additional Info</div></li>
Then, use the click function from jQuery .click( handler ), use it this way to know which one has been clicked :
$(".room").click(function(event){
var target = event.currentTarget;
var room = $(target).data("room");
alert(room);
});

Only show unique date values in ng-repeat list

I have a unordered list generated by an ng-repeat. In each list item I have a month header and a blog post.
I only want to show one instance of each month name but I can't work out a nice way of doing this without some really hacky jQuery.
Is there a way I can somehow detect this value in Angular and use an ng-hide to only show the first one of each type?
Maybe something like this could help, providing that your same-month posts are adjacent. If they are not, maybe it's okay to show the date altogether:
plnkr code example
Basically:
<li ng-repeat="post in model.blogPosts">
<span ng-show="model.blogPosts[$index - 1].date !== post.date">{{post.date}}</span>
<br>
<span>{{post.post}}</span>
</li>
Edit:
(Sorry for the default ul li styling, such uglyness)
You should probably modify your data to achieve this. Turn your post list into an object like
$scope.postsByMonth = {
October: [//...october posts],
November: [//...november posts],
//...
};
Then you can do something along these lines
<li ng-repeat-start="month, posts in postsByMonth">month<p>posts[0]</p></li>
<li ng-repeat-end ng-repeat="post in posts.slice(1)"><p>post</p>

Navigation Works Once, But Then Does Nothing

I'm trying to code a navigation bar with four elements. If the element is currently selected it will have a "red" background image, if it is one of the other 3, it will have a "black" background image. my four tabs are 'timetable, homework, notifications and sport'
I tried making 8 functions like the 2 below
function setTimeRed()
{
document.getElementById("time").style.ClassName = 'timetable_r';
}
function setTimeBlack()
{
document.getElementById("time").style.ClassName = 'time_r';
}
And then four blocks like this:
function changeTimeButton()
{
var timePath = new String();
timePath = document.getElementById("timetable").style.backgroundImage;
if(timePath == "url(assets/img/tabs/time_black.png)" || timePath == "")
{
setTimeRed();
setHomeBlack();
setNotiBlack();
setSportBlack();
}
else {
}
}
finally, my html has this:
<div id="tabbar">
<ul id="tabs">
<a href"#" onclick="changeTimeButton()">
<li id="timetable" class="time_b">
<p>Timetable</p>
</li>
</a>
<a href"#" onclick="changeHomeButton()">
<li id="homework" class="home_b">
<p>Homework</p>
</li>
</a>
<a href"#" onclick="changeNotiButton()">
<li id="notifications" class="noti_b">
<p>Notifications</p>
</li>
</a>
<a href"#" onclick="changeSportButton()">
<li id="sport" class="sport_b">
<p>Sport</p>
</li>
</a>
</ul>
</div>
It works once then does nothing. Why?
I think error is in your script, just one example
document.getElementById("time").style.ClassName = 'timetable_r';
which should be (there are no elements with id "time" in your html, at least in the code you posted here)
document.getElementById("timetable").style.ClassName = 'timetable_r';
Another thing, if it works once, then seems it might save some issues with new session or existing session. I am not an expert on javascript. But if it helps, please inform.
When turning the background color off, you need to remove any existing classes like this:
document.getElementById("timetable").className =
document.getElementById("timetable").className.replace
( /(?:^|\s)time_b(?!\S)/ , '' )
Since you're using classes instead of modifying the styles in the javascript, you should stick to that. You seem to be trying to set the background image in the javascript.
Instead, you should apply that background image to the class' styles in the CSS.
Using a framework like jQuery would make this much easier since it has helper functions such as addClass(), toggleClass(), and removeClass(). You should also set the 'a' tags inside the 'li'. It makes for cleaner code in my opinion. The browser will still read the click and be able to apply the classes correctly.
Also, you shouldn't have to repeat yourself so often in your code. One solution is to create a generic function and pass the element's id in as a parameter. Then, you use an 'active' class instead of 'timetable_r'. The active class will be applied to the active link and you won't have to write the functions out so many times. Hope this helps.

Updating an HTML list using Js

So I have a js game like scrabble. Now when the user makes a new word, I would like the word to be added to a list that is displayed in a div on my page.
The issue is I quite don't understand, how I could keep my old word created and insert a new word with new formatting and everything in a list form.
I know there is a list tag --
<ul>
<li>apple</li>
<li>ball</li>
</ul>
but what I can't really figure out is how do I use java script to enter the word as a new list entry.
I have used js to display the word created by the following syntax
document.getElementById('currentword').innerHTML = word;
where word is the variable that holds the current word created and currentword is the div id. but how do I use this kind of syntax for a list?
Please help!
Thanks
EDIT: I would also like the last entry to the list as the first item on my list. Seems like the list populates itself but the latest entry gets hidden and the list doesn't really auto scroll down as the items are added.
PS: Also incase someone knows how I could replace the tacky scroll bar option generated by CSS to a custom scroll bar. It would be great if you could point me in the correct direction!
Given a list:
<ul id="theList" >
<li>apple</li>
<li>ball</li>
</ul>
you could add an <li> like this (assuming that the variable word contains the word you want to add):
document.getElementById('theList').innerHTML += ('<li>'+word+'</li>');
There are other ways too, but this one is probably the simplest.
I use jQuery for dom manipulation and would recommend the same for you, it adds a lot of readability and tons of neat (x-browser friendly) functionality.
For example... the append api call would do the job if you were using jQuery.
<ul id="words">
<li>Some Word</li>
<li>Another Word</li>
</ul>
$("#words").append("<li>" + yourNewWord + "</li>");
Or with straight javascript...
document.getElementById('words').innerHTML += '<li>' + yourNewWord + '</li>';
EDIT:
I believe in motools the equivalent to .append is .grab
Basic idea:
var li = document.createElement("li");
li.innerHTML = "new text";
document.getElementById("TheULsId").appendChild(li);
<ul>
<li>apple</li>
<li>ball</li>
</ul>
then,
var newListItem = $('<li></li>').html("myNewWord");
$("ul").append(newListItem);
Well to the exact solution of my question, I figured out the rest from mootools docs :)
This fiddle demonstrated most of it.. http://jsfiddle.net/WngSS/1/
As for the scroll bar goes, well to customize ur own scrollbar you just use css effects.

Categories

Resources