Dynamically Expand Collapsible Content - javascript

I want to expand the collapsible content of a jQuery Mobile collapsible content section. I know I can click the heading to expand it, but I don't want to rely on the user to click the same section every time the page refreshes. I know I can set a variable in the html, but that won't do because the collapsible content will still close on postback.
I need this to be done with code rather than by the user. You can see my failed attempt below. I used the template from VS 2013's Web Forms project as a start then I added jQuery Mobile and followed the instructions from jQuery Mobile's site, or so I thought. This is a simplified test page but ultimately, I want to have an ASP.NET variables to detect whether, on postback, a section has already been clicked and if a collapsible section has already been clicked, open it again so the user doesn't have to click the same place again. Is there any way to persist the expanded state or dynamically expand jQuery Mobile's collapsible content?
<%# Page Title="Home Page" Language="VB" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.vb" Inherits="ExpandTest._Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<script>
$(".myDiv").trigger("expand");
</script>
<div class="jumbotron">
<h1>ASP.NET</h1>
<p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
<p>Learn more »</p>
</div>
<div class="row">
<div class="myDiv" data-role="collapsible">
<h2>Getting Started</h2>
<p>ASP.NET Web Forms lets you build dynamic websites using a familiar drag-and-drop, event-driven model. A design surface and hundreds of controls and components let you rapidly build sophisticated, powerful UI-driven sites with data access.
</p>
<p>
<a class="btn btn-default" href="http://go.microsoft.com/fwlink/?LinkId=301948">Learn more »</a>
</p>
</div>
</div>
</asp:Content>
-- EDIT --
Thing I have tried (even just for proof of concept) that fail:
$(".myDiv").trigger('expand'); // Apparently does not execute
$('.myDiv').on("click", alert("Fe Fi Foo Bar!");); // does not run anything within
$(document).on("pagecreate", function () {
Also, I have recently read that document.ready is supposed to be used for jQuery but not jQuery Mobile. Telling is the fact that I cannot use the same code that other user seem to think works and the same code that works in jsfiddle already. This leads me to believe I'm missing something that should be obvious. I have modified the order of loading jQuery Mobile in relation to the code to no avail.

Add an ASP.Net hidden field to the page with viewstate enabled.
The jQM collapsible has events for expand and collapse. On the client side, you can handle these events and create a list of the currently expanded collapsibles, and save this list to the hidden field. After postback, client code in the pagecreate event can read the list from the hidden field and expand those items.
Assign IDs to all the collapsible divs, then you can save a comma delimited list of IDs to the hidden input:
$(document).on("pagecreate", "#page1", function(){
var prevExpanded = $("#hidden").val().split(',');
$.each( prevExpanded, function( key, value ) {
$("#" + value).collapsible( "option", "collapsed", false );
});
$( "[data-role=collapsible]" ).on("collapsiblecollapse collapsibleexpand", function( event, ui ) {
GetAllExpanded();
});
});
function GetAllExpanded(){
var AllExpanded = [];
$( "[data-role=collapsible]" ).not(".ui-collapsible-collapsed").each(function( index ) {
AllExpanded.push($(this).prop("id"));
});
$("#hidden").val(AllExpanded.join(','));
}

Use <asp:hidden> fields, and on expand change their values. Then you will be able to set the value of $(".col-md-4").trigger("expand"); on postback.

Well the following works, although I'm still at a loss as to better ways that work on Web Forms and I'll have to find a way to conditionally load this, perhaps using hidden fields as suggested earlier. Thanks for the help.
<script type="text/javascript">
$(function () {
$("h2.ui-collapsible-heading").trigger("click");
});
</script>

Related

Loading different pages while keeping the same header

I have a question, I'm working on my first portfolio with html, css and javascript.It's just a simple site with a header with the nav menu and the body with some of my info, I was wondering if there's a way besides iframe to load only the body everytime I click a link without affecting the header:
<header>
<nav>
Home, about me, etc
</nav>
</header>
<body>
this is my home page
</body>
To really get in to one page app development using a library like Angularjs really does the trick. If you just need something really simple you can use the jQuery load function. For instance:
<body>
<button id="home">Home</button>
<button id="about">About</button>
<button id="examples">Examples</button>
<div id="content">
this is my home page
</div>
</body>
<script language="Javascript">
$("#home").click(function() {
$( "#content" ).load( "home.html" ); //Load all retrieved content
});
$("#about").click(function() {
//Only load content from a specific node
$( "#content" ).load( "about.html #desc" );
});
$("#examples").click(function() {
//More specific loading of node
$( "#content" ).load( "examples.html #storeMain .container" );
});
</script>
This is the same question that started me off learning to program.
Things have gotten a lot better as far as loading dynamic content on the fly... but also - much more complicated as far as setup / build tools / JS frameworks etc.
People will say --- just use HTML or PHP / and that it doesn't matter if the whole page is reloaded and the header repaints... but those people aren't like you. What if you want to look at a picture of the band WHILE listening to a song (myspace)... - or you want your header to fade to a different background and do an animation...
Here is a PHP example that explains it all: https://css-tricks.com/dynamic-page-replacing-content
Here is a hacky JS way to do it / where all of the info is on one page... but is hidden and then shown with JS / but - the URL isn't going to change: https://codepen.io/sheriffderek/pen/zxmjgr
// build a reusable function that switches the "view"
var switchView = function(trigger) {
$('.view').addClass('hidden');
var currentSection;
currentSection = $(trigger).data('view');
$('.' + currentSection).removeClass('hidden');
console.log("you are currently on:" + currentSection);
};
// when you click the menu item... run that function to switch to the associated "view" based on it's data attribute
$('.view-controls a').on('click', function() {
switchView(this);
});
$('.header').on('click', function() {
$('.compact-menu').toggleClass('active');
});
$('.compact-menu a').on('click', function() {
$('.compact-menu').removeClass('active');
}); // I had to add this code just to post a codepen link : /
Example in action: http://bryanleebrowncomposer.com
Not ideal... but if you aren't going to have URL change anyway... this is actually better for SEO - and it's easy - and gets you the snappy style.
Here is a JavaScript framework way: https://www.codementor.io/sheriffderek/less-than-ambitious-websites-with-ember-js-5mtthoijp
I love Ember.js - but if you were going to try your hand at another framework - I'd take a look at this vue.js way: https://scotch.io/tutorials/how-to-build-a-simple-single-page-application-using-vue-2-part-1
All roads lead to pain and suffering - for the most part. Good luck! Post your outcome, will yah?
You could dynamically load your pages and inject it to your main page (single page).
As another option, which is partially not what you are looking for, you can load different pages via url and then dynamically rendering a header/footer onload (multiple page). But multiple pages will allow you to avoid having to manipulate URL states manually through something like domain.com?page=about and it's generally much more manageable in terms of regular website development.
If I make it single page, I load the body content via ajax. Like so
<div class="header">Lorem ipsum</div>
<div class="content-wrapper">
<!--Load content HTML here via ajax -->
</div>
<div class="footer">Lorem ipsum</div>
For multi-page setups, I do this
<div class="header-wrapper">
<!--Load header HTML here via ajax or render them via a javascript component -->
</div>
<div class="content-wrapper">Lorem ipsum</div>
<div class="footer-wrapper">
<!--Load footer HTML here via ajax or render them via a javascript component -->
</div>
The ajax part is as simple as this. (using jQuery ajax, axios, or http)
$.ajax({
type : 'GET',
url : 'foo.html',
dataType : 'html',
success : function(data){
wrapper.innerHTML = data;
},
Look up dynamically loading html via ajax so that you don't have to constantly repeat yourself implementing the same headers/footers across your pages. OR, like I said, you can also make/adopt a UI component to do it for you without ajax.

How to access the webresource controls from another html webresource on CRM 2016 Form?

I have two html webresources in my customer form, one contains a multitab and second contains some tiles, designed using bootstrap and JQuery for events. Want to initiate a Click event of tab exist on first webresource on the click of tiles exist on second webresource.
I have prepared the script on simple html page first all code is working there but not on crm form.
How can I access the tab controls using JQuery from first webresource?
I have written some scripts on each html webresources, can I use the same script/function from another html webresource?
Webresource_1
//html
<div class="row">
<ul id="tab_container_01" class="nav nav-tabs">
<li id="tab_cases"><a id="ahref_cases" href="#">Cases</a></li>
</ul>
</div>
//script
//Following script is working fine on the same page
<script type="text/javascript">
$("ul.nav-tabs").on("click", "li", function () {
var selectedTabText = ($(this).find("a").text());
var tabs = window.parent.Xrm.Page.ui.tabs;
//Some toggle script
});
</script>
Webresource_2
//html
<div class="panel">
<div> Open Cases </div>
</div>
//script
<script type="text/javascript">
$(".panel").on("click", "div", function () {
// following not working on crm form
$("#tab_cases").addClass('active');
$("#tab_cases").parent().siblings().removeClass('active'); //length 0, id not detecting
//window.parent.$("#tab_cases").parent().siblings().removeClass('active');
/* trigger click event on the li */
//trying to use function written on webresource_1 script
$("#tab_cases").closest("ul.nav-tabs li").trigger('click'); //*Not Triggering*
});
</script>
Although, technically since you are all within CRM, and you won't have any Cross Domain Scripting issues, this may be a little over kill, you could use Window.Post Message from Frame1, to communicate to the CRM form, and then have it communicate to Frame 2. This would also mean that your scripts wouldn't have to be dependent on the DOM of each, other subscribe to the same interface for posting/receiving messages.

Trying to build a content locker using jQuery

I am very new to jQuery and not entirely sure what I'm doing. Will try my best to explain the problem I'm facing.
I'm trying to lock some content on a landing page until a user shares the link using FB, Twitter, LinkedIN or G+. The first version of the script I wrote (which worked fine) ran like this:
<head>
<script type="text/javascript">
...
$(document).ready(function()
{
$('.class').click(clearroadblock());
buildroadblock();
}
</script>
<style>
.class
{
[css stuff]
}
</style>
</head>
<body>
<div id="something">
<ul>
<li> Link1 </li>
<li> Link2 </li>
</ul>
</div>
</body>
The problem I'm now facing is changing out this code to replace the list elements with social share buttons. As they are no longer under .class, but classes like fb-share-button and twitter-share-button. Please help me understand what I need to modify to accommodate this? PS: This is not a Wordpress site.
function clearroadblock()
{
$('#roadblockdiv').css('display', 'none');
$('#roadblockBkg').css('display','none');
}
This is the way I'm clearing the overlay once a click is detected, BTW.
Can I wrap the social buttons in divs, assign them IDs and use those IDs to trigger the click like below?
<div id="Button">
Tweet
</div>
$('#Button').click(clearroadblock());
You can have multiple classes on an element by separating them with a space. Try the following:
class="class fb-share-button"
Your jquery will still work off the "class" class. I would recommend you change this name to something more meaningful though. Your css can target the "class" for general styles, but you can also target fb and twitter separately.
Update
I decided to create a quick JSFiddle for this.
Some of the styles etc won't be the same as what you're doing, but the problem is resolved. I've created a div with id main that contains the content that you want to hide. There's an absolutely positioned div over the top of this, this is the roadblock. The javascript is showing the roadblock (assuming that's what you wanted to do with buildroadblock()).
On click of a link in the ul with id socialMedia we call clearroadblock. Notice the lack of parenthesis. This hides the roadblock.
This isn't a great way of preventing someone from seeing information, you might want to think about pulling the content down from the server when the action is performed, however, I think this answers your question.

Dynamic Content Swap via AJAX

Only this much now: I'm creating a vcard design for myself. My motivation is to make it look as good as possible. I want to apply to a webdesign company with this vcard to get a professional education for webdesign.
I still have a lot to change till it completely fulfills in my requirements, but this is my current version of the design I just uploaded to get you an overview over the design.
So as you can see it's focused on retro, vintage, ribbons and scetch elements.
Right know I want to get rid of these jerking content refreshs. So I thought a dynamic content swap via ajax and jQuery would be the best way to do it.
I never did much with js or actually ajax.
I want to ask you guys about a solution you think benefits in my design. I was thinking about something smoothly.
The content which needs to be changed is placed in
<nav>
(...)
<ul class="ribbon s"><!--Following links got the class="ribbon b/p/l/k"-->
<li class="ribbon-content">Link</li>
<!--
?content=blog
?content=portfolio
?content=lebenslauf
?content=kontakt
-->
</ul>
(...)
</nav>
<section id="content">
<div class="con clearfix">
(...)
</div><!--An empty div for possibly swapping without touching the vintage paper thing -->
</section>
http://robert-richter.com/boilerplate/
for example use jquery.
first add jquery to your html. within the domready-event you can register click events on your ribbon-menue. on each click you load the div-content from the given link-url in the html-part.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$.ready(function(){
$(".ribbon-content a").on("click", function(event){
event.preventDefault();
$(".con").load($(event.target).attr("href"), function(){
// add code after loading - for example change classes of menue
})
});
})
</script>
additionly you can the the browser-history to enable the prev- and next-buttons of the browser.

Better alternative to an iframe to display tab content?

I have a page with an iframe to feature the contents of the clicked tab. There are 3 tabs and 1 iframe. The sources of the contents relating to each tab clicked are formatted and coded in other html & css files.
What is another alternative to using an iframe, because I noticed that when the tab is clicked, it still shows the white background, similar to when a new page is loading?
Here's my code:
<div id="tabs">
<div id="overview">
<a target="tabsa" class="imagelink lookA" href="toframe.html">Overviews</a>
</div>
<div id="gallery">
<a target="tabsa" class="imagelink lookA" href="tawagpinoygallery.html">Gallery</a>
</div>
<div id="reviews">
<a target="tabsa" class="imagelink lookA" href="trframe.html">Reviews</a>
</div>
</div>
<div id="tabs-1">
<iframe src="toframe.html" name= "tabsa" width="95%" height="100%" frameborder="0">
</iframe>
</div>
The only alternative to using IFRAMEs to load dynamic content (after the page has loaded) is using AJAX to update a container on your web page. It's pretty elegant and usually faster than loading a full page structure into an IFRAME.
Ajax with JQuery (use this and you will be loved on SO; the AJAX functions are great and simple)
Ajax with Prototype
Ajax with MooTools
Standalone Ajax with Matt Kruse's AJAX toolbox (Used to use this, using JQuery today because I needed a framework)
AJAX with Dojo (Said to be fast, but AJAX is not as straightforward)
Another alternative is to use AJAX to load the content of a tab and use a div to display the content. I would suggest that using an existing Tab library might be an option rather than trying to solve all the problems associated with creating tabs.
Maybe the jQuery UI Tab might be helpful here if you like to try it.
EDIT: AJAX example with UI Tabs.
First, the HTML will look like this.
<div id="tabs">
<ul>
<li><span>Overviews</span></li>
<li><span>Gallery</span></li>
<li><span>Reviews</span></li>
</ul>
</div>
Then make sure that you import the appropriate jQuery files:
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js" type="text/javascript"></script>
etc...
Then add the code to create the tabs:
<script type="text/javascript">
$(function() {
$("#tabs").tabs();
});
</script>
There's an alternative to AJAX!
You can load ALL three possible contents into separate DIVs.
Then clicking on a tab will simply make the display attribute of the appropriate content's DIV "block" while making the other two DIVs' display property "none".
Cheap, easy, does not require AJAX costs for extra http request or for coding.
Mind you, AJAX is a better solution if the contents of the tabs will change dynamically based on other data as opposed to being known at the time the page loads.
You don't need script.
<ul><li>foo link<li>bar link</ul>
<div class="tab" id="foo">foo contents</div>
<div class="tab" id="bar">bar contents</div>
Plus this CSS, in most browsers: .tab:not(:target) { display: none !important; }, which defaults to all content visible if :target isn't supported (any modern browser supports it).
If you're showing content with script, always hide it with script. Let it degrade gracefully if that script doesn't run.
It's probably better to load in the content for each tab into DIVs on the same page and then switch the visibility of each DIV when a tab button is clicked using JavaScript and the CSS display property.
If you can't do that then iframe is probably the best solution. You can make the iframe background transparent, see below:
<iframe src="toframe.html" name= "tabsa" width="95%" height="100%" frameborder="0" allowtransparency="true"></iframe>
You would then need to add the following CSS to the BODY element using:
BODY { Background: transparent; }
The HTML iframe is to be used to include/display non-template content, such as a PDF file. It's considered bad practice when used for template content (i.e. HTML), in both the SEO and UX opinions.
In your case you just want to have a tabbed panel. This can be solved in several ways:
Have a bunch of links as tabs and a bunch of div's as tab contents. Initially only show the first tab content and hide all others using CSS display: none;. Use JavaScript to toggle between tabs by setting CSS display: block; (show) and display: none; (hide) on the tab content divs accordingly.
Have a bunch of links as tabs and one div as tab contents. Use Ajax to get the tab content asynchronously and use JavaScript to replace the current tab contents with the new content.
Have a bunch of links as tabs and one div as tab contents. Let each link send a different GET request parameter or pathinfo representing the clicked tab. Use server-side flow-control (PHP's if(), or JSP's <c:if>, etc) or include capabilities (PHP's include(), or JSP's <jsp:include>, etc) to include the desired tab content depending on the parameter/pathinfo.
When going for the JavaScript based approach, I can warmly recommend to adopt jQuery for this.
This is jQuery example that includes another html page into your document. This is much more SEO friendly than iframe. In order to be sure that the bots are not indexing the included page just add it to disallow in robots.txt
<html>
<header>
<script src="/js/jquery.js" type="text/javascript">
</header>
<body>
<div id='include-from-outside'></div>
<script type='text/javascript'>
$('#include-from-outside').load('http://example.com/included.html');
</script>
</body>
</html>
You could also include jQuery directly from Google: http://code.google.com/apis/ajaxlibs/documentation/ - this means optional auto-inclusion of newer versions and some significant speed increase. Also, means that you have to trust them for delivering you just the jQuery ;)
As mentioned, you could use jQuery or another library to retrieve the contents of the HTML file and populate it into the div. Then you could even do a fancy fade to make it look all pretty.
http://docs.jquery.com/Ajax/jQuery.get
Something along these lines:
$.get("toframe.html", function(data){
$("#tabs-1").html(data);
});
edit..
you could prepopulate or onclick you could do the get dynamically
$("#tabs a").click(function(){
var pagetoget = $(this).attr("href");
$.get...
})
If you prepopulate could have three containers instead of the one you have now, 2 hidden, 1 display, and the click functions will hide them all except for the one you want.
The get is less code though, easier time.

Categories

Resources