Fancybox Jquery - Pass variable to iframe ( [duplicate] - javascript

I am trying to open a fancybox iframe on my page. Pass over some basic information to the iframe. Then I want to make it so that the iframe talks back to it's parent.
I am passing nameid-1 throughout statically, though I would really like to have this as variable such as: var nameid=$(this).attr('nameid')
I just don't know how to execute this all correctly as I am new to Ajax/Javascript and struggling with the logic.
Base.html
JS:
<script type='text/javascript'>
//<![CDATA[
// Popup Function
$(document).ready(function () {
$('a.openinformation').fancybox({
openEffect: 'fade',
openSpeed: 500 //,
});
});
// Update from iFrame
function setInformation(userText) {
$('#displayfield-nameid-1').html(userText);
$('#showhide-nameid-1').show();
}
//]]>
</script>
HTML:
<div>
<a class="openinformation fancybox.iframe" href="iframe.html" nameid= "1" originalname="Mary Poppins" >Mary Poppins</a>
</div>
<div id ="showhide-nameid-1" style=" display:none; background:#0CF;">
<p>Replacement Name: <span id="displayfield-nameid-1"></span></p>
</div>
iframe.html
JS :
<script type='text/javascript'>
//<![CDATA[
// Start
$(window).load(function () {
// When Loaded get going.
$(document).ready(function () {
$('a.doupdate').click(function () {
parent.setInformation($(this).text());
parent.$.fancybox.close();
});
$('a.closeremove').click(function () {
parent.$('#showhide-nameid-1').hide();
parent.$.fancybox.close();
});
});
});
//]]>
</script>
HTML
<p>The old name: $originalname;</p>
<p>The id for this column is: $nameid</p>
<p>Please select a new name:</p>
<div><a class="doupdate" href="#">Display new married name : Mary Smith</a></div>
<div><a class="doupdate" href="#">Display new married name: Sandy Shore</a></div>
<div><a class="closeremove" href="#" id="1">Clear (Hide) married Names Box</a></div>

Your question can be dived in two parts :
How to pass data (stored in variables) from parent page to an iframe (opened in fancybox)
How to manipulate data (and/or store such data in variables) inside the iframe and then pass those values to the parent page when fancybox is closed.
1). Pass data from parent page to (fancybox) iframe
I think your best choice is to store all your data in a single javascript object like :
var parentData = {};
... so you can pass a single object to the iframe instead of several variables. Then you can add different properties and values to that object like :
parentData.nameid = "1";
parentData.originalname = "Mary Poppins";
... or more if you need so.
You still may want to pass that information statically through (HTML5) data attributes like :
<a data-nameid="1" data-originalname="Mary Poppins" href="iframe.html" class="openinformation">Mary Poppins</a>
... and push the data values into the parentData object within the fancybox beforeLoad callback like :
beforeLoad : function () {
parentData.nameid = $(this.element).data("nameid");
parentData.originalname = $(this.element).data("originalname");
}
... that would give you much more flexibility IMHO.
Now, the only thing you need to do in the iframed page is to refer to those properties as parent.parentData.nameid and parent.parentData.originalname any time you need them, e.g.
having this html (iframe.html)
<p>The old name: <span id="originalname"></span></p>
<p>The id for this column is: <span id="nameid"></span></p>
... you can use this script to write the values of the parent object like :
$("#nameid").text(parent.parentData.nameid);
$("#originalname").text(parent.parentData.originalname);
Notice you cannot do (as in php)
<p>The old name: $originalname;</p>
... so we used <span> tags to write their content via javascript.
2). Pass data from iframed page to parent page.
First thing you need to do is to declare in your parent page, an object to store data from the iframe and a function to process it like :
var iframeData = {};
function setInformation(data) {
return iframeData = data;
};
Then in the iframed page, you can write different properties/values to the iframeData object and run the setInformation() function (in the parent page) from the iframe to pass the values to the parent page like :
$(".doupdate").on("click", function (e) {
e.preventDefault();
iframeData.newname = $(this).find("span").text(); // set object property/value
parent.setInformation(iframeData); // pass it to parent page
parent.$.fancybox.close();
});
The code above assumes you have a similar html like
<a class="doupdate" href="#">Display new married name : <span>Mary Smith</span></a>
... notice I wrapped the name I want pass in a span tag. Optionally you could separate it in 2 spans like :
<span class="fname">Mary</span><span class="lname">Smith</span>
... and write them in separated values like :
iframeData.fname = $(this).find("span.fname").text();
iframeData.lname = $(this).find("span.lname").text();
For the clear button, I would just reinitialize the variable and close fancybox like
$('a.closeremove').on("click", function (e) {
e.preventDefault();
iframeData = {}; // reset variable
parent.setInformation(iframeData); // pass it to parent page
parent.$.fancybox.close();
});
... and perform the manipulation of the parent page from the parent page itself using the fancybox afterClose callback like :
afterClose : function () {
if ( objLength(iframeData) > 0 ) {
$('#displayfield-nameid-1').html(iframeData.newname);
$('#showhide-nameid-1').show();
} else {
$("#displayfield-nameid-1").empty();
$('#showhide-nameid-1').hide();
}
}
... notice I will only show the selector #showhide-nameid-1 if the iframeData object's length is bigger than 0. Because that, I need a function to validate the object's length :
Based on this answer, you could do:
function objLength(iframeData) {
// ref https://stackoverflow.com/a/5533226/1055987
var count = 0, i;
for (i in iframeData) {
if (iframeData.hasOwnProperty(i)) {
count++;
}
}
return count;
};
... which will return the object's length.
Last note :
Since the iframed page is referring to the parent page using the prefix parent, it will return js errors if it's opened outside an iframe. You may want to validate first if the iframed page is actually contained inside an iframe before trying to access data back and forth to/from the parent page like :
if (window.self !== window.top) {
// the page is inside an iframe
}
See DEMO and feel free to explore the source code of both pages.

Related

Fancybox (jQuery) - Passing information from parent to iframe and iframe back to parent

I am trying to open a fancybox iframe on my page. Pass over some basic information to the iframe. Then I want to make it so that the iframe talks back to it's parent.
I am passing nameid-1 throughout statically, though I would really like to have this as variable such as: var nameid=$(this).attr('nameid')
I just don't know how to execute this all correctly as I am new to Ajax/Javascript and struggling with the logic.
Base.html
JS:
<script type='text/javascript'>
//<![CDATA[
// Popup Function
$(document).ready(function () {
$('a.openinformation').fancybox({
openEffect: 'fade',
openSpeed: 500 //,
});
});
// Update from iFrame
function setInformation(userText) {
$('#displayfield-nameid-1').html(userText);
$('#showhide-nameid-1').show();
}
//]]>
</script>
HTML:
<div>
<a class="openinformation fancybox.iframe" href="iframe.html" nameid= "1" originalname="Mary Poppins" >Mary Poppins</a>
</div>
<div id ="showhide-nameid-1" style=" display:none; background:#0CF;">
<p>Replacement Name: <span id="displayfield-nameid-1"></span></p>
</div>
iframe.html
JS :
<script type='text/javascript'>
//<![CDATA[
// Start
$(window).load(function () {
// When Loaded get going.
$(document).ready(function () {
$('a.doupdate').click(function () {
parent.setInformation($(this).text());
parent.$.fancybox.close();
});
$('a.closeremove').click(function () {
parent.$('#showhide-nameid-1').hide();
parent.$.fancybox.close();
});
});
});
//]]>
</script>
HTML
<p>The old name: $originalname;</p>
<p>The id for this column is: $nameid</p>
<p>Please select a new name:</p>
<div><a class="doupdate" href="#">Display new married name : Mary Smith</a></div>
<div><a class="doupdate" href="#">Display new married name: Sandy Shore</a></div>
<div><a class="closeremove" href="#" id="1">Clear (Hide) married Names Box</a></div>
Your question can be dived in two parts :
How to pass data (stored in variables) from parent page to an iframe (opened in fancybox)
How to manipulate data (and/or store such data in variables) inside the iframe and then pass those values to the parent page when fancybox is closed.
1). Pass data from parent page to (fancybox) iframe
I think your best choice is to store all your data in a single javascript object like :
var parentData = {};
... so you can pass a single object to the iframe instead of several variables. Then you can add different properties and values to that object like :
parentData.nameid = "1";
parentData.originalname = "Mary Poppins";
... or more if you need so.
You still may want to pass that information statically through (HTML5) data attributes like :
<a data-nameid="1" data-originalname="Mary Poppins" href="iframe.html" class="openinformation">Mary Poppins</a>
... and push the data values into the parentData object within the fancybox beforeLoad callback like :
beforeLoad : function () {
parentData.nameid = $(this.element).data("nameid");
parentData.originalname = $(this.element).data("originalname");
}
... that would give you much more flexibility IMHO.
Now, the only thing you need to do in the iframed page is to refer to those properties as parent.parentData.nameid and parent.parentData.originalname any time you need them, e.g.
having this html (iframe.html)
<p>The old name: <span id="originalname"></span></p>
<p>The id for this column is: <span id="nameid"></span></p>
... you can use this script to write the values of the parent object like :
$("#nameid").text(parent.parentData.nameid);
$("#originalname").text(parent.parentData.originalname);
Notice you cannot do (as in php)
<p>The old name: $originalname;</p>
... so we used <span> tags to write their content via javascript.
2). Pass data from iframed page to parent page.
First thing you need to do is to declare in your parent page, an object to store data from the iframe and a function to process it like :
var iframeData = {};
function setInformation(data) {
return iframeData = data;
};
Then in the iframed page, you can write different properties/values to the iframeData object and run the setInformation() function (in the parent page) from the iframe to pass the values to the parent page like :
$(".doupdate").on("click", function (e) {
e.preventDefault();
iframeData.newname = $(this).find("span").text(); // set object property/value
parent.setInformation(iframeData); // pass it to parent page
parent.$.fancybox.close();
});
The code above assumes you have a similar html like
<a class="doupdate" href="#">Display new married name : <span>Mary Smith</span></a>
... notice I wrapped the name I want pass in a span tag. Optionally you could separate it in 2 spans like :
<span class="fname">Mary</span><span class="lname">Smith</span>
... and write them in separated values like :
iframeData.fname = $(this).find("span.fname").text();
iframeData.lname = $(this).find("span.lname").text();
For the clear button, I would just reinitialize the variable and close fancybox like
$('a.closeremove').on("click", function (e) {
e.preventDefault();
iframeData = {}; // reset variable
parent.setInformation(iframeData); // pass it to parent page
parent.$.fancybox.close();
});
... and perform the manipulation of the parent page from the parent page itself using the fancybox afterClose callback like :
afterClose : function () {
if ( objLength(iframeData) > 0 ) {
$('#displayfield-nameid-1').html(iframeData.newname);
$('#showhide-nameid-1').show();
} else {
$("#displayfield-nameid-1").empty();
$('#showhide-nameid-1').hide();
}
}
... notice I will only show the selector #showhide-nameid-1 if the iframeData object's length is bigger than 0. Because that, I need a function to validate the object's length :
Based on this answer, you could do:
function objLength(iframeData) {
// ref https://stackoverflow.com/a/5533226/1055987
var count = 0, i;
for (i in iframeData) {
if (iframeData.hasOwnProperty(i)) {
count++;
}
}
return count;
};
... which will return the object's length.
Last note :
Since the iframed page is referring to the parent page using the prefix parent, it will return js errors if it's opened outside an iframe. You may want to validate first if the iframed page is actually contained inside an iframe before trying to access data back and forth to/from the parent page like :
if (window.self !== window.top) {
// the page is inside an iframe
}
See DEMO and feel free to explore the source code of both pages.

JavaScript detect in which element an object is created

Note:
This question is marked as a duplicate but I'm not looking to get the script element but the div element as seen in my code where the script is in.
Whereas the "duplicate" is looking to get the script tag. this is not the case with my script.
I am using JavaScript for my current project and was wondering if there is a way to detect which HTML element an object was created in.
Consider the following code.
Editable.js
function Editable(elem, form1, form2) {
this._edit_form;
this._value_form;
this._current_form;
//Getters
this.getEditForm = function() { return this._form1; };
this.getValueForm = function() { return this._form2; };
this.getCurrentForm = function() { return this._current_form; };
//Setters
this.setCurrentForm = function(current_form) { this._current_form = current_form; };
this.switch = function() {
if(_current_form == _edit_form)
_current_form = _value_form;
else
_current_form = edit_form;
};
var __construct = function() {
$(this.elem).html(this._value_form);
}();
}
-
<html>
<head>
<script src='Editable.js'></script>
</head>
<body>
<div>
<script>new Editable(this, "Company Name", "<input type='text' placeholder='enter a company name' />");</script>
</div>
</body>
</html>
The point of an editable is that it has a value form and an edit form.
I want to be able to switch between those by removing the text from the element and placing an HTML Input field.
This change is supposed to happen when clicking the element.
The problem now is that "this" logs as
Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
While the object would need to know what element it is in so it may edit it's contents.
So I would need the DIV HTML element for that.
Thank you very much.

Creating a way to navigate back when using jQuery for AJAX

I am dynamically loading content into part of a page using jQuery .load().
It is working well, but I am having trouble building a way for the user to navigate back to the original content after the new content has been loaded.
I have created a 'close' icon with css which exists on the new page which is loaded, but I am not sure how to set up the jQuery / JavaScript in order for it to navigate the user back to the original state of that part of the page.
This is the relevant js:
// pages to load
var loadLudwig = "lw.html";
$("#work a:first-child").click(function() {
$("#work").fadeTo('slow', 0, function() {
$("#work").load(loadLudwig, function(){
$("#work").fadeTo('slow', 1);
});
});
});
// (& this part is working fine)
The relevant HTML (on the original page) is like this (its a grid of images embedded within anchor tags):
<section id="work">
...img and svg stuff
</section>
I tried many variations of:
$("#close-button").click(function() {
$("#work").fadeTo('slow', 0, function () {
$("#work").load('home.html #work', function() {
$("#work").fadeTo('slow', 1);
});
});
});
but this loads the content very strangely / some of the original functionality of #work is lost.
How do I get my close button to navigate back to the original state of #work?
In the jquery documentation for .load() is stated that:
Script Execution
When calling .load() using a URL without a suffixed selector
expression, the content is passed to .html() prior to scripts being
removed. This executes the script blocks before they are discarded. If
.load() is called with a selector expression appended to the URL,
however, the scripts are stripped out prior to the DOM being updated,
and thus are not executed. An example of both cases can be seen below:
Here, any JavaScript loaded into #a as a part of the document will
successfully execute.
1. $( "#a" ).load( "article.html" );
However, in the following case, script blocks in the document being
loaded into #b are stripped out and not executed:
1. $( "#b" ).load( "article.html #target" );
This is a probable cause for lack of functionality.
I'd also look into event binding. In your code examples you're using .click but if you are loading content or you are creating elements on-the-fly you should be favoring .on(). This method delegates events instead of just binding them to a DOM node.
I'd recommend you reading the whole article.
EDIT:
Here is a quick n'dirty way of achieving the effect
// pages to load
var loadLudwig = "lw.html",
$ludwig,
$work = $('#work'),
$workContent = $work.children(),
$closeButton = $("#close-button");
$work.find('a:first-child').click(function() {
$work.fadeTo('slow', 0, function() {
//Here is the tricky part
//Detaching keeps all the jQuery data on the elements
$workContent.detach();
//The first time, load the content,
//if the content is already loaded
//append it to the container
if(!$ludwig){
$work.load(loadLudwig, function(){
//Save the content in a var
//so you can reuse it later
$ludwig = $work.children();
$work.fadeTo('slow', 1);
});
} else {
$ludwig.appendTo($work);
$work.fadeTo('slow', 1);
}
});
});
$closeButton.click(function() {
$work.fadeTo('slow', 0, function () {
//Remove the old content, don't worry
//because is stored in $ludwig
$work.children().detach();
//Instead of reloading the content, just
//attach the fragment again
$workContent.appentTo($work);
$work.fadeTo('slow', 1);
});
});
You probably need to save the html somewhere. For example:
// Top of file
var oldHTML = "";
// Lots of stuff...
$("#work a:first-child").click(function() {
$("#work").fadeTo('slow', 0, function() {
// Store the old html
oldHTML = $("#work").html();
$("#work").load(loadLudwig, function(){
$("#work").fadeTo('slow', 1);
});
});
});
// Code for the close button
$("#close-button").click(function() {
$("#work").fadeTo('slow', 0, function () {
$("#work").html(oldHTML).fadeIn("slow");
});
});
Alternatively, instead of replacing the html, you could create another child. Of course, you might have to slightly change your markup.
<section id="work">
<div id="oldHTML">
...img and svg stuff
</div>
<div id="newSection" style="display:none;">
</div>
</section>
Then replace $("#work") with $("#oldHTML") in your first piece of code like so:
$("#oldHTML a:first-child").click(function() {
$("#oldHTML").fadeTo('slow', 0, function() {
$("#oldHTML").hide();
$("#newSection").load(loadLudwig, function(){
$("#newSection").show().fadeTo('slow', 1);
});
});
});
// Code for the close button
$("#close-button").click(function() {
$("#newSection").fadeTo('slow', 0, function () {
$("#newSection").hide();
$("#work").fadeIn("slow");
});
});

Can't find the first direct child element of a div

Below is the code generating jQuery UI dialog from existing HTML template.
I want to extract title attribute from the HTML and use it as the title parameter for jQuery UI dialog method.
I tried children().first(), find(">:first-child"), etc but nothing worked.
titleStr is just undefined.
function define_Window() {
// constructor of class Window
MyNS.Window = function (path_html) {
this.DIV = $("<div/>").load(path_html);
var titleStr = this.DIV.children().first().attr("title");
// To test if DIVs are well appended
this.DIV2 = $("<div/>").attr("name", "Form").load(path_html);
$(MyNS.Windows).append(this.DIV2);
this.DLG = this.DIV.dialog({
title: titleStr
});
Template HTML files look like this:
<div title="THIS IS TITLEEEEEE!!!!">
<p>Description goes here</p>
<form>
<fieldset>
<label for="">blahblahblah
have you tried
var titleStr = "";
this.DIV = $("<div/>").load(path_html, function complete(responseText, textStatus, XMLHttpRequest) {
titleStr = $("div").first.attr("title");
} );
explanation: load gets the template through an asynchronous ajax request. therefore, the div alement carrying the title might not be available when you query for it in your code.
closure code adopts the call signature used by the jquery api spec for load.
I think in your case you don't need Child, try this:
First you are selecting this.DIV = $("div")
So, This will return array of elements. You can select the first by using this:
var first_div = this.DIV.eq(0)
// Now you can select its title:
first_div.attr('title');

Creating Dynamic Javascript AJAX

Alright, I'm currently working to create on an account mainpage a applet to show each "kid" the user has registered to the site. My idea is simple :
Kid 1 / Kid 2 / Kid 3
As buttons (with style and such) when he goes on this page. When he clicks on one of those buttons/names, I use javascript to show the description of the infos of the kid, etc. When I click on another name, the current content closes and shows the new appropriate content.
The content is dynamically created, so the id's of the divs containing the info are named after the number of kids. Example : content_Info_Kid1, content_Info_Kid2, ... It doesnt matter how many kids there are, they will be named content_Info_Kid32 if need be.
Now, I'm not too comfy with AJAX and javascript in general. In fact, I am not at all.
My first idea was to do this in a separate javascript file.
$(document).ready(function() {
$("#content_info_kid1").hide();
$("#content_info_kid2").hide();
$("#content_info_kid3").hide();
$("#KID_1").click(function () {
if ($("#content_info_kid1").is(":hidden")){
$("#content_info_kid2").hide();
$("#content_info_kid3").hide();
$("#content_info_kid1").show("slow");
$(this).css("font-weight","bold");
$("#KID_2").css("font-weight","normal");
$("#KID_3").css("font-weight","normal");
}
});
$("#KID_2").click(function () {
if ($("#content_info_kid2").is(":hidden")){
$("#content_info_kid1").hide();
$("#content_info_kid3").hide();
$("#content_info_kid2").show("slow");
$(this).css("font-weight","bold");
$("#KID_1").css("font-weight","normal");
$("#KID_3").css("font-weight","normal");
}
});
$("#KID_3").click(function () {
if ($("#content_info_kid3").is(":hidden")){
$("#content_info_kid2").hide();
$("#content_info_kid1").hide();
$("#content_info_kid3").show("slow");
$(this).css("font-weight","bold");
$("#KID_1").css("font-weight","normal");
$("#KID_2").css("font-weight","normal");
}
});
});
Obviously, this is not dynamic. And I don't want to create 32 alternatives, of course. Can somebody point me the right direction to create a dynamic way to show my content based on the number of kids ?
EDIT (see bottom for updated on loading just one kid data at a time)
An example on how you could achieve that:
<style type='text/css' media='screen'>
button { margin-left:20px; display:inline; }
</style>
<script type='text/javascript' src='jquery-1.7.1.min.js'></script>
<script type='text/javascript'>
function loadKidData(kidID) {
switch (kidID) {
case 1 : $('#kName').text(' John Doe');
$('#kNickname').text(' Speedy');
$('#kHobbies').text(' Booling');
break;
case 2 : $('#kName').text(' Mathews Doe');
$('#kNickname').text(' Slowy');
$('#kHobbies').text(' Basketball, baseball');
break;
case 3 : $('#kName').text(' Jackson Doe');
$('#kNickname').text(' J-DOE');
$('#kHobbies').text(' Archery');
break;
case n : $('#kName').text(' Enne Doe');
$('#kNickname').text(' The-Nanny');
$('#kHobbies').text(' Anything goes');
break;
default : $('#kName').text('');
$('#kNickname').text('');
$('#kHobbies').text('');
}
}
jQuery( function () {
$('.nav').click( function () {
loadKidData($(this).html().replace('KID ','')*1.0); // *1.0 same as parseInt(...,10).
})
});
</script>
</head>
<body>
<button class='nav' >KID 1</button><button class='nav' >KID 2</button><button class='nav' >KID 3</button>
<div id='KID_INFO' style='margin:20px auto; overflow:auto; ' >
<p>Name:<span id='kName'></span></p>
<p>Nickname:<span id='kNickname'></span> </p>
<p>Hobbies:<span id='kHobbies'></span> </p>
</div>
</body>
Sample at: http://zequinha-bsb.int-domains.com/kidsinfo.html
Now, as far as dynamically displaying the data, it will have to do with your resources: database? If so, you could read the data and pass it over:
$.get('url-of-the-database-reading-script',function (data) {
// assumed all data comes back formatted:
$('#KIDS_INFO').html(data);
});
I can/could help you further, more details would help. Are you using classic asp (.asp); php; etc?
EDIT:
Instead of this:
jQuery( function () {
$('.nav').click( function () {
loadKidData($(this).html().replace('KID ','')*1.0); // *1.0 same as parseInt(...,10)
})
});
Do this:
jQuery( function () {
$('.nav').click( function () {
$.get('your-data-fetching-url?kidID='+$(this).html().replace('KID ','')*1.0, function (data) {
//assumed the data comes back formatted:
$('#KIDS_DATA').html(data);
})
})
});
Note that I put a question mark at the end of the url; followed by the querystring kidID=
Give each "Kid" button the same class and use that for the click handler. From there, you can associate the "content_info_kid" with the "kid" button either by
1)Using the index of the element. The button for kid2 should be index 1 relative to its parent and the content_info for kid2 should also be index 1 relative to its parent.
or
2)Extract the number from the ID of the button.
Both approaches are documented below.
$('.kid_button').click(function(){
// get number from index (this starts at '0')
// if your kid #'s start at 1, you should add 1 to this
var id = $(this).index();
// OR...get number from id where id format is kid_{#}
var id = $(this).attr('id').split('_').pop();
// now we have the number to append to everything else
// we should also associate all "content_info" with a class
// which we will call "kid_content"
if($("#content_info_kid"+id).is(":hidden")){
// hide all of the 'kid_contents'
$(".kid_content").hide();
// show the one we want
$("#content_info_kid"+id).show("slow");
// normalize all buttons
$(".kid_button").css("font-weight","normal");
// bold this one
$(this).css("font-weight","bold");
}
});

Categories

Resources