Load js when visible - javascript

I have a phtml page that has separate tabs
<div id="maintabs">
<ul id='mainTabNav'>
<li>Tab 1</li>
<li>Tab 2</li>
</ul>
<div id="maintabs-1">
<p><?php require_once VIEW_DIR."somewhere/tab1.phtml"; ?></p>
</div>
<div id="maintabs-2">
<p><?php require_once VIEW_DIR."somewhere/tab2.phtml"; ?></p>
</div>
</div>
Each tab/page has a header with a js source specific to the page like this
<script src="js/tab<num>.js"></script>
On the page load though each javascript file is loading. Is there a way to only load the js for the tab currently open? When a new tab opens then the js reloads with just the js for the current tab?

You could keep click events on each of the main tabs that would dynamically load the appropriate javascript using something like jQuery.getScript().
$('div[id^="#maintabs"]').click(function(e){
var tabno = $( this ).index();
$.getScript("js/tab"+tabno);
});
The pitfall I'd imagine with this is that you seem to want to have all the previous javascript to be washed away once the latest JS file was loaded. I'm not sure if that's doable or if you'll have side effects from it.
Also this could totally be done with vanilla JS but well, time savings.

Is there a way to only load the js for the tab currently open?
Since you are using PHP you could manage to pass the number of the current page to view. Pseudo-code
View::factory('templateView')
->set('page_number', $page_number)
The $page_number variable now holds the page number that can be used in your scripts with ease
<script src="js/tab<?php echo $page_number; ?>.js"></script>
...
<div id="maintabs">
<ul id='mainTabNav'>
<li>Tab 1</li>
<li>Tab 2</li>
</ul>
<div id="maintabs-".<?php echo $page_number; ?>>
<p><?php require_once VIEW_DIR."somewhere/tab".<?php echo $page_number; ?>.".phtml"; ?></p>
</div>
</div>

Can't you just put this:
<script src="js/tab<num>.js"></script>
into your somewhere/tab*.phtml?

Using pure Javascript, I believe it is possible if you are loading the page using AJAX.
This tutorial, http://code.tutsplus.com/tutorials/how-to-load-in-and-animate-content-with-jquery--net-26, demonstrates a way of loading another page (I call them child pages) into the main page (which I call the index page). As far as I can tell, if you include associated script tags in the child pages rather than the index page, then they are dynamic in that they load when the child page loads, and unloads when he child page unloads.
I have used a modified version of this tutorial in my own projects before, where I don't create the child pages with the same content as the index page as the tutorial shows, and instead use the whole child html file solely for only the child page's content.
Here’s an example based off your code:
indexScript.js :
/* When index.html is loaded and ready */
$(document).ready(function() {
/* Handels on-click of menu buttons */
$('#mainTabNav a').click(function(){
/* Getting the linked page */
var toLoad = $(this).attr('href');
/* Hiding content and calling loadContent function - creates animation*/
$('#contentDiv').hide('slow', loadContent);
/* Injects content to contentDiv div tag */
function loadContent(){
$('#contentDiv').load(toLoad, '', showNewContent);
}
/* Shows contentDiv div */
function showNewContent() {
$('#contentDiv').show('normal');
}
demonstratePageChange(); //For testing - you can remove this
/* In order to stop the browser actually navigating to the page */
return false;
});
/* Initial Load - load first child page by simulation of clicking on it*/
$('#maintabs_1').click();
});
/* To demonstrate the respective JS script is loaded as needed */
function demonstratePageChange() {
setTimeout(function(){
alert(testMsg); //Alerts the message from resepctive child page script
}, 3000);
}
index.html :
<!DOCTYPE html>
<html>
<head></head>
<body>
<div id='maintabs'>
<ul id='mainTabNav'>
<a id='maintabs_1' href='childA.html'><li>Tab 1</li></a>
<a id='maintabs_2' href='childB.html'><li>Tab 2</li></a>
</ul>
</div>
<div id='contentWrapper'>
<div id='contentDiv'></div>
</div>
</body>
<script type='text/javascript' src='jquery-2.1.1.min.js'></script>
<script type='text/javascript' src='indexScript.js'></script>
</html>
childA.html :
<div id='maintabs-1' class='contentBody'>
<script type='text/javascript' src='childAScript.js'></script>
Child A - Page
</div>
childAScript.js :
console.log("childAScript has been loaded");
var testMsg = "This is Child A";
childB.html :
<div id='maintabs-2' class='contentBody'>
<script type='text/javascript' src='childBScript.js'></script>
Child B - Page
</div>
childBScript.js :
console.log("childBScript has been loaded");
var testMsg = "This is Child B!!!!";
However, there are few things to consider using this method:
This particular method requires jQuery
This method doesn't support reload, you'd have to code that in. i.e. if you're on tab 2, you need store that fact and on refresh, point back to tab 2.
Local testing - as far as I can tell, only FF supports this when testing it locally. If you want to test this on Chrome for example, you'd need to upload this onto a server and only then will this work. This is due to the "XMLHttpRequest cannot load" error, if you try this locally.
I hope this helps and resolves your problem.

The use of AMD requirejs can do this also. It is possible to use pure js although I prefer AMD modules [i.e. define()]. For my apps depending on user actions, code is downloaded on the fly reducing load. An onclick event fires on the tab control calling requirejs and the script get downloaded and you call it. PsuedoExample:
<script type="text/javascript" src="require.js"></script>
$(document).ready(function() {
//Assuming using jQuery, use document.getElementById and what not otherwise
$('#maintabs-1').click(function(e) {
require(['/js/tabnum1.js'], function (tab1) {
tab1(doStuff);
});
});
}
Use a for loop for multiple tabs. Also, I try and put as much processing [sans data storage and server validation (obviously)] into the client side.

Related

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.

Using jquery load() to add content into tabbed navigation

I have a web application that uses tabbed navigation from a UI kit: http://www.getuikit.com/docs/tab.html.
Each tab will load different content, which is broken down into several php scripts, one per tab.
One (not very efficient, but so for successful) option is to load up all of the tabs content when the page first loads, so to use the standard example:
<!-- This is the container of the toggling elements -->
<ul data-uk-switcher="{connect:'#my-id'}">
<li><a id="1" class="load-tab" href="">Tab 1</a></li>
<li><a id="2" class="load-tab" href="">Tab 2</a></li>
</ul>
<!-- This is the container of the content items -->
<ul id="my-id" class="uk-switcher">
<li><?php require('script1.php'); ?></li>
<li><?php require('script2.php'); ?></li>
</ul>
I want to avoid this though, because the scripts are quite hefty so want to load them on demand for better user experience.
So what I've done is instead add holding divs and target them with a jQuery load():
<!-- This is the container of the content items -->
<ul id="my-id" class="uk-switcher">
<li><div id="1"></div></li>
<li><div id="2"></div></li>
</ul>
jq:
$(document).on("click", "a.load-tab", function(){
//get the value of the tab clicked in the nav
var tab = $(this).attr('id');
//determine the filename to load based on tab clicked
if (tab == '1'){ var filename = 'script1.php'; }
if (tab == '2'){ var filename = 'script2.php'; }
//load it
$( "#"+tab+ ).load( filename );
});
This works fine ... ish.
Question is this: With the initial (non jquery) method, each script could use the main page's core files that have already been included, e.g. header.php, functions.php etc etc. But when the content is loaded from jquery it seems each script needs to be included in the scipt1.php file and loaded again, which results in duplicate content being created in the DOM.
EDIT
script1.php currently is structured something like:
<?php
require('header.php');
require('connect.php');
require('setUser.php');
require('setParams.php');
require('functions.php');
?>
<div id="header">
//header content
</div>
<table>
//table content
</table>
The page that the navigation sits within, let's just call it index.php for now, already must have those php files included, so you can see the duplication issue.
What can be done to avoid this? Thought of a few options like iframes but seems like it might be a hack.
Your issue is essentially inside 'script1.php' you have something that requires 'connect.php' / data that is populated. But you are doubling up on DOM elements when you pull that in.
Two solutions to that issue are: 1 - create slimmer versions of your lib php files that don't include any DOM elements, only the data required to populate script1.php's data, or
script1.php contains
<?php
require('header.php');
require('connect.php');
require('setUser.php');
require('setParams.php');
require('functions.php');
?>
<div id="header">
//header content
</div>
//Everything inside #content is what you want to pull in
<div id="content">
<table>
//table content
</table>
</div>
And then call
$("#1").load("script1.php #content");
This will only load the HTML that is inside the #content div.

Overriding a javascript function in a Wordpress Child Theme

I am writing a simple Wordpress child theme.
There is a portfolio feature which uses flexslider to display the thumbnail from the most recent posts and, when clicking on them, it uses ajax to open up the post content in a div on the page.
I have written a category page based on this, which pulls out all the post categories and displays the thumbnail for the most recent post. However, when I click on the thumbnail, I need the page to go to a new page and not open up in the content div.
The problem is, I am reusing code which looks a bit like this:
<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
<div class="flexslider">
<ul class="slides">
<li>
<a href="http://the-url-here">
<img src="<?php echo $thumb[0]; ?>" />
</a>
</li>
</ul>
</div>
<?php endwhile; ?>
But there is custom js within the parent theme global footer as follows which handles the opening up of the content, rather than redirecting to the location specified in the tag as usual.
$(".flexslider ul.slides li a").live('click', function(e){ e.preventDefault();
/*Set Function Variables */
$this = $(this);
$selectedthing = $this;
$postId = $($this).attr('data-url');
// and so on...
return false;
});
So, I need to disable the javascript attached to .flexslider ul.slides li a on that one single page template only, preferably without having to change the classes, as I think thatwould open up another can of worms around the css. Remember the theme loads the javascript in the footer, so I assume any changes Imake in the page template will be overridden in the footer.
Any ideas on the best way to approach this?
Just remove click live listener in your child theme. Add this javascript only for that specific page template.
$(".flexslider ul.slides li a").die('click');

Load Same Code Twice In Separate Div

I'm creating a resource database that has a scrolling container on the side. Essentially, when you click a thumbnail within the container, it will load the contents of a div which will fade in and display content for that category. Each div tag looks something like this:
<div>
<h2>Category1</h2>
<p><a style="float:right" class="a_demo_four" href="/Resources/file1.pdf" target="_blank">
Download
</a>File Desc</p>
<hr/>
</div>
And will load as such:
Essentially, I want to be able to display the same exact content when I open another category on this page. I have several different categories, and want to be able to pull the code from say Category1, Category2, and so on and so forth so I can display all of them in a "View All" tab. I've attempted to use jQuery's load function as seen below:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script>
$(function() {
$("#includedContent").load("b.html");
});
</script>
</head>
<body>
<div id="includedContent"></div>
<h1>This is why I rule</h1>
</body>
</html>
to load the content from the original div into the view all category, but nothing shows up. Unfortunately, I have very limited knowledge with Javascript/jQuery so I'm having difficulty being able to use the same content in a different div without just copying and pasting the code over. This would also pose problems in the future when I am adding files and have to edit the code twice if I did so.
Thank you in advance!
You can keep your content in a variable like this:
var content = '';
$(document).ready(function(){
//load first in a div
$('#includedContent').load('b.html', function(result){
content = result;
//from here on, you know you have b.html data in the variable content
//and you can use it elsewhere like this
$('#anotherDivId').html(content);
});
});
If you call your code within document ready function will work.
Try,
$(document).ready(function(){
$("#includedContent").load("b.html");
});
However you will probably need to keep it somewhere as visualex suggested in order to add the content in multiple places as you require.
This is a working jsfiddle,
http://jsfiddle.net/c5SAH/show/
it loads content from
http://jsfiddle.net/gfgE8/show/

calling an external script and .load jquery conflict

I'm pretty sure this is another DOH! facepalm questions but as designer and not a programmer I need some help getting it right.
What I have is an index file calling local .html files via jQuery .load. Just like this:
(some tabs functionality not relative here - thus the link target call)
Lightbox</li>
<div id=lightbox">
<div class="load">
<script type="text/javascript">
$('.load').load('examples/lightbox.html');
</script>
</div>
</div>
I also have an external .js file that has a bunch of functions that handles some lightboxes among other things. Standard <script src="js/typography.js" type="text/javascript"></script>
Which contains:
$(document).ready(function(){
$(".open-lightbox").on("click", function(){
$('.lightbox').css('display','block');
});
$('.close-lightbox').click(function(){
$('.lightbox').css('display','none');
});
});
My problem is that if the externally called .html file has any elements dependent on the .js file ie. the lightbox popup it doesn't work.
something like :
LightBox Link
<div class="lightbox">
lightbox content
Close
</div>
If i move the html code right to the index page instead of the .load, no problem, same if I moved the JS as an inline <script>...</script> rather than calling it extrenally. Works fine in both cases.
My spidey sense tells me this has something to do with my function and .load not executing in the order I need them to, but my javascript copy/paste skills only go this far.
Can anyone tell me if I can make this combination work? I'd really appreciate it.
EDIT
Maybe I explained my self poorly so let me try and post a better example.
If my index code is as followed everything works: My lightbox pops up as intended.
<li>Link to open Tab Content</li>
<div id="thistabid">
<--Tab Content below-->
<div class="somehtmlpage-load">
LightBox Link
<div class="lightbox">
lightbox content
Close
</div>
</div>
<--End Tab Content-->
</div>
When the said tab is clicked the content inside "thistabid" show up. Whatever that content may be.
Now if i do :
<li>Link to open Tab Content</li>
<div id="thistabid">
<--Tab Content below-->
<div class="somehtmlpage-load">
<script type="text/javascript">
$('.somehtmlpage-load').load('examples/lightbox.html');
</script>
</div>
<--End Tab Content-->
</div>
The lightbox doesn't work. The content of lightbox.html is
LightBox Link
<div class="lightbox">
lightbox content
Close
</div>
Same as the html in the 1st example where everything works. The only difference it's being jQuery loaded rather than hard coded.
What I mean by "if the externally called .html file has any elements dependent on the .js file ie. the lightbox popup" is that if the html is part of the externally called file then the lightbox function isn't working. If it's hard coded it pops up like intended.
On 1st glance the .on seems like should be the solution but most likley my implementation of it is off the mark :/
The 'on' or the 'live' function needs to be applied through an element that exists on the page. Generally some parent of the actual element is used. Can you try something on the following lines with the correct references to the elements on your page:
<li>Link to open Tab Content</li>
<div id="thistabid">
<--Tab Content below-->
<div class="somehtmlpage-load">
<!--leave tab empty for now -->
</div>
<--End Tab Content-->
</div>
<script>
(function(){
$('.somehtmlpage-load').load('examples/lightbox.html');
//live or on needs to be applied to an element that exists on th page
$('#thistabid').on('click', '.open-lightbox', function(){
$('.lightbox').css('display','block');
});
$('#thistabid').on('click', '.close-lightbox', function(){
$('.lightbox').css('display','none');
});
})();
</script>
There seems to be a race condition between your load() and document ready.
To address this you'll need to:
either wait for the load() to complete before you attach the click events
or attach the click to the container of your load() step and use event delegation.
See this page and this other one for more information on how to use on() for delegation.
The code would look like this:
$(".somehtmlpage-load").on("click", ".open-lightbox", function(){
$('.lightbox').css('display','block');
});
Using a SSI solved my problem. I was trying to keep it all Local Drive friendly but it seemed to be causing more problems than anticipated.
Pick your favorite dev environment...I didn't run into any conflicts on either.
ASP - <!--#include file = "examples/lightbox.html" -->
PHP - <?php include 'examples/lightbox.html';?>
Just in case someone else runs into a similar problem.

Categories

Resources