Html change div content - javascript

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>

Related

How to create a see-more/Read-more feature requiring only anchors in the html?

I'm working on a site which will be maintained by not so tech savvy people, and I need to be able to give them the ability to add "see-more" anchors which use Jquery slide up/down to reveal their content.
My code works well for a single instance of the read more, but when there are multiple instances of this, it gets fairly screwed up.
javascript/jquery
$(".see-more").nextUntil(".see-less").wrapAll("<div class='see-more-content'></div>");
$(".see-less").hide();
var count= 1
/*
$(".see-more-content").each(function(){
var count= count+1;
$(this).data("count",count);
console.log(count);
});
*/
$(".see-more-content").slideUp(0);
$(".see-more").click(function(){
$(".see-more-content").slideToggle();
$(".see-more").hide();
$(".see-less").show();
});
$(".see-less").click(function(){
$(".see-more-content").slideToggle();
$(".see-less").hide();
$(".see-more").show();
});
HTML
<a class="see-more">See More...</a>
<ul>
<li>Advanced Elastic search Technology </li>
<li>Document Text Search</li>
<li>Embed Code Web Publishing for Images, Video & PDFs</li>
<li>Video Management with HTML5 Full</li>
<li>Previews On the Fly Conversions and Transcoding</li>
<li>Print on Demand</li>
<li>Stylized Collections (Lightboxes/Galleries)</li>
<li>Alerts and Notifications</li>
<li>Comments, Ratings and Favorites</li>
<li>WordPress and Drupal CMS Integrations</li>
<li>Dropbox Integration</li>
<li>Asset Level Performance Analytics • Site Activity Analytics Dashboard</li>
<li>Unlimited Custom User Access Levels</li>
<li>Integrated Content Contribution and Workflow</li>
<li>Personal Profile Management</li>
<li>Mobile App and Site </li>
<li>Watermarking</li>
<li>Rights Management</li>
<li>All New Feature Releases3</li>
</ul>
<a class="see-less">See Less...</a></div>
What I want to happen:
I want everything between the anchor with class see-more and anchor with class see-less, to get wrapped in a div, which when the anchor for see-more is clicked that div jquery slides down, when see-more is clicked, and slides up when see-less is clicked.
What is happening:
It works perfect when there is only one instance of see-more and see-less in a page. https://jsfiddle.net/TheWebTech/by3LsLuu/
When there are multiple instances of see-more and see-less in the html, the contents of all see-more+see-less blocks after the first instance are all moved/wrapped into the first block instances of the see-more see-less blocks get added.
https://jsfiddle.net/TheWebTech/by3LsLuu/4/
How do I prevent everything from being wrapped into the first instance of the see-more see-less block and instead have each one get wrapped separately?
Bonus but not really required: how can I make each see-more section slide up/down separately from eachother?
If you're going to keep the layout the same, you can use .prev() and .next() jQuery methods to determine which selector group you're referring too. Here's an updated fiddle with two instances:
https://jsfiddle.net/szva79d6/1/
First, I've made it so that your wrapping function applies to each selector individually, like so:
$(".see-more").each(function() {
$(this).nextUntil(".see-less")
.wrapAll("<div class='see-more-content'></div>");
});
What I've done in the two event methods is to make each event only act on the previous or next siblings, so that your events are properly delegated to each dynamically wrapped element.
$(".see-more").click(function() {
var $more = $(this),
$content = $more.next(".see-more-content"),
$less = $content.next(".see-less");
$content.slideToggle();
$more.hide();
$less.show();
});
$(".see-less").click(function() {
var $less = $(this),
$content = $less.prev(".see-more-content"),
$more = $content.prev(".see-more");
$content.slideToggle();
$less.hide();
$more.show();
});
You need to target specific to itself, try this:
$(".see-more").click(function(){
$(this).next(".see-more-content").slideToggle(); // find next content and show
$(this).hide(); // hide the see more button
$(this).nextAll('.see-less').first().show(); // show the next see less button
});
$(".see-less").click(function(){
$(this).prev(".see-more-content").slideToggle();
$(this).hide();
$(this).prevAll(".see-more").first().show();
});
Here's an updated fiddle

Appearance of a selected menu item in master page

I have a web application with one master page that contains the menu, and several .aspx pages. The menu is something like https://jsfiddle.net/96bd8y0z/
<style>
a, a:visited { color:black }
a.link.active { color:blue; }
<style>
<script>
$(function () {
$('a.link').click(function () {
$('a.link').removeClass('active');
$(this).addClass('active');
});
});
<ul>
<li>Home</li>
<li>News</li>
<li>Contact</li>
<li>About</li>
</ul>
It works fine in the fiddle: When you select one of the links in the menu, its appearance changes, in the fiddle from black to blue. But when I try to apply this scheme in my web application, the link that I select (say: 'News') becomes blue for a second, the hyperlink page ('News') is loaded, 'News' becomes black again, and the the menu entry 'Home' becomes blue again.
I can understand that this happens because the master page section is re-loaded but I don't know how to solve it.
Is there a way to keep the selected option active (i.e. keep 'News' blue)?
I believe this question is similar to How to make menu by using Master Page with jquery?, but the user that answered this question found this question unclear and his answer did not solve it for me.
It probably would be better to do it in the back-end: keep a variable in aspx that specifies in which page you are, and then in the master page, compare that variable for each menu, and add the "active" class only to the one that you want.
If you want to do it with JavaScript, you could do one thing: when the link is clicked, save the index of the menu element, then when the page is reloaded, mark that element as the active one.
Something like this:
$(function() {
$('a.link').click(function() {
$('a.link').removeClass('active');
$(this).addClass('active');
// save the index for later (notice it's the index of the li, not the a)
localStorage.setItem("active", $(this).parent().index());
});
// read the previous index or initialize to the first one if first time
var active = localStorage.getItem("active") ? localStorage.getItem("active") : 0;
// add the active class to the element
$("ul li:nth-child(" + (parseInt(active)+1) +") a").addClass("active");
});
You can see it working on this JSFiddle: https://jsfiddle.net/96bd8y0z/6/ (rerun or reload the page to see how the blue link remains). But again, doing it in the back-end would be better.
Well, menu is re-rendered on each page request, it`s evident that all classes added on previous page opening would disappear.
So, in order to make needed menu item selected, there should be a check for every link: if it`s href attribute is equal to the route of the loaded page, then add "active" class to it.
Meanwhile, it`s a bad practice to do it with javascript, better do it while building template. But if it has to be done with js, you probably can do something like this (using jquery for links selection):
$(function() {
var links = $('.link');
for (var i = links.length; i--;) {
var _this = $(links[i]);
if (document.URL.split('http://site-domain.net')[1] == _this.attr('href')) {
$('.link').removeClass('active');
_this.addClass('active');
}
}
});
Here is the fiddle example:
https://jsfiddle.net/96bd8y0z/4/

Styling Dynamically Added Content

So I've looked online in this issue, but can't seem to find the answer. Let me explain my problem fully.
I'm trying to dynamically add content to an <ul> and have it all formatted correctly. What I'm inserting to is this:
<ul data-role="listview" id="localStoresUL" data-autodividers="true" data-divider-theme="d">
</ul>
I have a list item somewhere else that is clicked and loads this up with data, and I am doing that with the following code:
$("#localStores").click(function() {
Customer.getLocalStores(13, 12, function(stores){
for(var i = 0; i < stores.length; i++){
$("#localStoresUL").append('<li class="store" id="' + stores[i].id + '"><a data-transition="slide" data-filter="false">' + stores[i].fullname + '</a></li>');
}
});
});
Now this works all fine and dandy the first time the user clicks the link and it populates that <ul>. But I have a back button on the page using this code:
<a href="#" class="ui-btn-left back" data-rel="back" data-icon="back" data-add-back-btn="true" >Back</a>
And when the user clicks this back button and then clicks on the previous <li> again (which should populate the <ul>) the content is loaded dynamically, but not formatted at all. I have no idea why this is happening. Does this problem make sense, and does anybody have any tips for how to fix it?
Not sure why it does. It shouldn't.
You need to call .refresh() on the listview.
Generally, if content is loaded but not formatted, you have an issue with your CSS. Inspect the loaded elements with firebug and see what classes are present and style rules are being applied. Then double check that your relevant CSS selectors match those elements.

Compress HTML - Elements?

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.

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.

Categories

Resources