JQuery Mobile, one footer fragment for whole site - jquery-mobile

I'm not asking how to get a fixed footer.
I've a structure with both multi-page and single page.
I'd like to know how to use only one html fragment for the whole site. I'm really looking for a solution because I'd like to edit the footer in only one place and see the modification in all pages.
Thanks.
EDIT:
I'm developing a mobile application to be wrapped with PhoneGap, so I'm looking for client side solutions.
SOLUTION (pushing together the solutions by #maco and adapting them to my case):
$(function() {
// load the templates
$('body').append('<div id="module"></div>');
$('#module').load('templates/module.html :jqmData(role="page")',function() {
// save the actual footer and header
var hdhtml = $('#module :jqmData(role="header")').clone();
var fthtml = $('#module :jqmData(role="footer")').clone();
// removes the header/footer
$(':jqmData(role="header")').remove();
$(':jqmData(role="footer")').remove();
// load at the correct place the header/footer
$(':jqmData(role="page")').prepend(hdhtml).append(fthtml).page().trigger('pagecreate');
// delete the temporary div
$($(this).html()).replaceAll(this).attr('id', 'module');
});
// set the class "ui-btn-active" for the active page
$(document).live('pagecreate', function() {
// get the current page
var currentPage = window.location.pathname;
currentPage = currentPage.substring(currentPage.lastIndexOf("/") + 1, currentPage.length).split("&")[0];
// remove the class from the footer
$($.mobile.activePage + ':jqmData(role="footer") li a')
.removeClass('ui-btn-active ui-state-persist');
// add the class to the link that points to the particular href
$($.mobile.activePage + ':jqmData(role="footer") li a[href="' + currentPage + '"]').addClass('ui-btn-active ui-state-persist');
});
});

module.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>module header</h1>
</div>
<div data-role="footer" class="ui-bar">
<h3>module footer</h3>
</div>
</div>
</body>
</html>
module.js (load this in all pages)
function module() {
var fthtml = $('#module :jqmData(role="footer")').clone();
$(':jqmData(role="footer")').remove();
$(':jqmData(role="page")').append(fthtml).page().trigger('pagecreate');
}
$(function(){
$('body').append('<div id="module"></div>');
$('#module').load('YOUR_module.html_PATH :jqmData(role="page")',function(){
$($(this).html()).replaceAll(this).attr('id','module');
module();
});
$(':jqmData(role="page")').live('pageinit',module);
});
YOUR_module.html_PATH (eg. "../module.html", "../module/module.html")

If you are generating HTML pages server side,
You can use your server language (php,java,node) templating capabilities to insert a HTML from common file.
i.e. for jsp
</div>
<jsp:include page="scripts/footer.jsp" />
.....
</body>
And if you are doing heavy stuff in javascript than use any javascript templating engine.
ie.e http://handlebarsjs.com/

I solved this by creating partial footer view and calling it where I need it: #Html.Partial("Footer")

Related

How change meta tags to make page more SEO firendly for both AJAX and none-AJAX requests in MVC 5

I have some pages that clients can request them with AJAX or none-AJAX requests and for SEO purpose i need to change meta tags for AJAX requests dynamically with Javascript (that seems is possible now) but i dont know what is best practice to do this?
My first solution is something like this:
views:
#{
var title = "title";
var keywords = "p1,p2";
var description = "des";
if (Request.IsAjaxRequest()) { Layout = null; }//else i have a default layout for that!
}
#section metas{
<title>#title</title>
<meta id="keywords" name="keywords" content="#keywords">
<meta id="description" name="description" content="#description">
}
<div id="main">
#{
if (#Request.IsAjaxRequest())
{
<script>
document.title = "#title";
document.getElementById('keywords').setAttribute("content", "#keywords");
document.getElementById('description').setAttribute("content", "#description");
</script>
}
}
...
And
_Layout:
<head>
<meta charset="UTF-8">
#RenderSection("metas", required: false)
...
<div class="content">
#RenderBody()
....
(Views will send as response data and will rewrite content of div with id="content" for AJAX requests).
It seems work fine but i am not sure it is a good solution.
any help appreciate!.

Dynamic section name in wicked_pdf header

In Wicked_pdf I have several sections. Each section is starts a new page and is started by a header like so:
<h2 class="section" style="color: #0050b2;font: arial, sans-serif;font-size: 17;">Application details</h2>
In my header I would like to display the section name on the first and all subsequent pages that belong to this section. I know that this would be Javascript / jQuery, but my skills in this area are woefully inadequate.
Any help would be greatly appreciated.
Take a look at this code snippet below, taken from WickedPDF Readme:
<html>
<head>
<script>
function number_pages() {
var vars={};
var x=document.location.search.substring(1).split('&');
for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}
var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];
for(var i in x) {
var y = document.getElementsByClassName(x[i]);
for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];
}
}
</script>
</head>
<body onload="number_pages()">
Page <span class="page"></span> of <span class="topage"></span>
</body>
</html>
Especially this line:
var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];
These are special parameters made available on each PDF pages, accessible via document.location.search. For your case, luckily subsection contains the text content of element in your PDF pages.
Now, to achieve the dynamic header, in your controller you need to specify the :header, and point it to an erb file which contains:
<html>
<head>
<script>
function subst() {
var vars={};
var x=document.location.search.substring(1).split('&');
for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}
document.getElementById('dynamic-header').innerHTML = vars['section'];
}
</script>
</head>
<body onload="subst()">
<h2 id="dynamic-header">Replace me!</h2>
</body>
</html>
The header will be replaced by the element found inside your PDF page. This also solves your dynamic requirement, because vars['section'] will contain the same content until it finds another with different content. Please note that I haven't tested the code above, but I hope you get the idea.

Navbar content loading all options

I have a navbar in Jquery mobile which have 5 contents, each content have a text right now. The problem is that the first time that I load the page, in the first tab all the content is loaded, and as soon as you start pressing the buttons, the content is loaded normally, as shown in the image below:
Then when I start clicking the buttons the content shows correctly:
Below is the code that I'm using:
Javascript:
<script>
(function($) {
// Before handling a page change...
$(document).bind("pagebeforechange", function(e, data)
{
// If the new page is not being loaded by URL, bail
if (typeof data.toPage !== "string")
{
return;
}
// If the new page has a corresponding navbar link, activate its content div
var url = $.mobile.path.parseUrl(data.toPage);
var $a = $("div[data-role='navbar'] a[href='" + url.hash + "']");
if ($a.length)
{
// Suppress normal page change handling since we're handling it here for this case
e.preventDefault();
}
// If the new page has a navbar, activate the content div for its active item
else
{
$a = $(url.hash + " div[data-role='navbar']").find("a.ui-btn-active");
// Allow normal page change handling to continue in this case so the new page finishes rendering
}
// Show the content div to be activated and hide other content divs for this page
var $content = $($a.attr("href"));
$content.siblings().hide();
$content.show();
});
})(jQuery);
Here is the HTML:
<body>
<div data-role="page">
<div data-role="header">
<div data-role="navbar">
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
</ul>
</div>
</div>
<center>
<div data-role="content">
<div id="oneContent">First</div>
<div id="twoContent">Second</div>
<div id="threeContent">Third</div>
<div id="fourContent">Fourth</div>
<div id="fiveContent">Fifth</div>
</div>
</center>
</div>
</body>
How can avoid the problem of loading all content at first load?
UPDATED TO ANSWER NEW REQUEST BELOW
If you want the first tab to show up by default, set the CSS of them all individually then toggle them into view.
First put this in your <head> or in a linked CSS file:
<style>[data-role=content] > div { display: none; }</style>
Then insert these two lines into your Javascript at the beginning like so:
(function ($) {
$(document).ready(function() {
var path = (window.location.hash) ? window.location.hash : '#oneContent';
$(path).show();
});
$(document).bind("pagebeforechange", function (e, data) {
....
Here's an updated fiddle diddle skittle

Jquery tab re-addition

I am trying to add undo/redo functionality in Jquery tabs. I am able to store and restore li/divs for added/removed tab.
Issue is when I re-add tab to the form, though it is added properly as li and div for that particular tab are present and can be seen. But if I click on that tab 'tabsselect' event is not getting fired. Li and div for tab look in order. But I am not able to figure what is missing.
In my website I am dynamically adding and removing tabs and it is working fine but just readding of once removed tab isnt working
Here is the code for adding tab
var $tabs = $("#tabs").tabs({
tabTemplate: "<li><a href='#{href}'>#{label}</a> <span id='id1' class='ui-icon ui-icon-close'>Remove Tab</span></li>",
add: function (event, ui) {
var tab_content = $tab_content_input.val(); // || "Tab " + tab_counter + " content.";
}
});
Here is the removal code
$("#tabs span.ui-icon-close").live("click", function () {
if (imode == 1) {
var index = $("li", $tabs).index($(this).parent());
if ($tabs.tabs("length") > 1) {
$tabs.tabs("remove", index);
}
}
});
Nothing fancy really. Looking for answers.
Thanks
Try This code out this will give you a nice example to manipulate data in tabs using jquery.
JavaScript
$(document).ready(function(){
var $tabs = $('#tabs').tabs();
var $a = $('<a />').appendTo('body').attr('href','#').html('add new tab').click(function(){
var n = parseInt($tabs.tabs( "length" ),10)+1;
$('body').append('<div id="tabs-'+n+'">content for the tab # '+ n +'</div>');
$tabs.tabs("add",'#tabs-'+n,'Tab #'+n);
return false;
});
$('<a/>').html('<br><br>remove tab').attr('href','#').click(function(){
$tabs.tabs('remove',$tabs.tabs('length')-1);
return false;
}).appendTo('body');
});
HTML
<!DOCTYPE html>
<html>
<head>
<link class="jsbin" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"></link>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
article, aside, figure, footer, header, hgroup,
menu, nav, section { display: block; }
</style>
</head>
<body>
<div id="tabs">
<ul>
<li>Nunc tincidunt</li>
<li>Proin dolor</li>
<li>Aenean lacinia</li>
</ul>
<div id="tabs-1">
<p>Tab 1 content</p>
</div>
<div id="tabs-2">
<p>Tab 2 content</p>
</div>
<div id="tabs-3">
<p>Tab 3 content</p>
</div>
</div>
</body>
</html>
*
Just use the id's of the selected tabs and manipulate data in them. this will allow to add and remove tabs on your page
*
Tab Select Function
$('.ui-tabs-nav').bind('tabsselect', function(event, ui) {
ui.options // options used to intialize this widget
ui.tab // anchor element of the selected (clicked) tab
ui.panel // element, that contains the contents of the selected (clicked) tab
ui.index // zero-based index of the selected (clicked) tab
});
Use ui.index to get the index of the selected tab and then add then manipulate the selected tab .

How do you post to an iframe?

How do you post data to an iframe?
Depends what you mean by "post data". You can use the HTML target="" attribute on a <form /> tag, so it could be as simple as:
<form action="do_stuff.aspx" method="post" target="my_iframe">
<input type="submit" value="Do Stuff!">
</form>
<!-- when the form is submitted, the server response will appear in this iframe -->
<iframe name="my_iframe" src="not_submitted_yet.aspx"></iframe>
If that's not it, or you're after something more complex, please edit your question to include more detail.
There is a known bug with Internet Explorer that only occurs when you're dynamically creating your iframes, etc. using Javascript (there's a work-around here), but if you're using ordinary HTML markup, you're fine. The target attribute and frame names isn't some clever ninja hack; although it was deprecated (and therefore won't validate) in HTML 4 Strict or XHTML 1 Strict, it's been part of HTML since 3.2, it's formally part of HTML5, and it works in just about every browser since Netscape 3.
I have verified this behaviour as working with XHTML 1 Strict, XHTML 1 Transitional, HTML 4 Strict and in "quirks mode" with no DOCTYPE specified, and it works in all cases using Internet Explorer 7.0.5730.13. My test case consist of two files, using classic ASP on IIS 6; they're reproduced here in full so you can verify this behaviour for yourself.
default.asp
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Form Iframe Demo</title>
</head>
<body>
<form action="do_stuff.asp" method="post" target="my_frame">
<input type="text" name="someText" value="Some Text">
<input type="submit">
</form>
<iframe name="my_frame" src="do_stuff.asp">
</iframe>
</body>
</html>
do_stuff.asp
<%#Language="JScript"%><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Form Iframe Demo</title>
</head>
<body>
<% if (Request.Form.Count) { %>
You typed: <%=Request.Form("someText").Item%>
<% } else { %>
(not submitted)
<% } %>
</body>
</html>
I would be very interested to hear of any browser that doesn't run these examples correctly.
An iframe is used to embed another document inside a html page.
If the form is to be submitted to an iframe within the form page, then it can be easily acheived using the target attribute of the tag.
Set the target attribute of the form to the name of the iframe tag.
<form action="action" method="post" target="output_frame">
<!-- input elements here -->
</form>
<iframe name="output_frame" src="" id="output_frame" width="XX" height="YY">
</iframe>
Advanced iframe target use
This property can also be used to produce an ajax like experience, especially in cases like file upload, in which case where it becomes mandatory to submit the form, in order to upload the files
The iframe can be set to a width and height of 0, and the form can be submitted with the target set to the iframe, and a loading dialog opened before submitting the form. So, it mocks a ajax control as the control still remains on the input form jsp, with the loading dialog open.
Exmaple
<script>
$( "#uploadDialog" ).dialog({ autoOpen: false, modal: true, closeOnEscape: false,
open: function(event, ui) { jQuery('.ui-dialog-titlebar-close').hide(); } });
function startUpload()
{
$("#uploadDialog").dialog("open");
}
function stopUpload()
{
$("#uploadDialog").dialog("close");
}
</script>
<div id="uploadDialog" title="Please Wait!!!">
<center>
<img src="/imagePath/loading.gif" width="100" height="100"/>
<br/>
Loading Details...
</center>
</div>
<FORM ENCTYPE="multipart/form-data" ACTION="Action" METHOD="POST" target="upload_target" onsubmit="startUpload()">
<!-- input file elements here-->
</FORM>
<iframe id="upload_target" name="upload_target" src="#" style="width:0;height:0;border:0px solid #fff;" onload="stopUpload()">
</iframe>
This function creates a temporary form, then send data using jQuery :
function postToIframe(data,url,target){
$('body').append('<form action="'+url+'" method="post" target="'+target+'" id="postToIframe"></form>');
$.each(data,function(n,v){
$('#postToIframe').append('<input type="hidden" name="'+n+'" value="'+v+'" />');
});
$('#postToIframe').submit().remove();
}
target is the 'name' attr of the target iFrame, and data is a JS object :
data={last_name:'Smith',first_name:'John'}
If you want to change inputs in an iframe then submit the form from that iframe, do this
...
var el = document.getElementById('targetFrame');
var doc, frame_win = getIframeWindow(el); // getIframeWindow is defined below
if (frame_win) {
doc = (window.contentDocument || window.document);
}
if (doc) {
doc.forms[0].someInputName.value = someValue;
...
doc.forms[0].submit();
}
...
Normally, you can only do this if the page in the iframe is from the same origin, but you can start Chrome in a debug mode to disregard the same origin policy and test this on any page.
function getIframeWindow(iframe_object) {
var doc;
if (iframe_object.contentWindow) {
return iframe_object.contentWindow;
}
if (iframe_object.window) {
return iframe_object.window;
}
if (!doc && iframe_object.contentDocument) {
doc = iframe_object.contentDocument;
}
if (!doc && iframe_object.document) {
doc = iframe_object.document;
}
if (doc && doc.defaultView) {
return doc.defaultView;
}
if (doc && doc.parentWindow) {
return doc.parentWindow;
}
return undefined;
}
You can use this code, will have to add proper params to be passed and also the api url to get the data.
var allParams = { xyz, abc }
var parentElm = document.getElementBy... // your own element where you want to create the iframe
// create an iframe
var addIframe = document.createElement('iframe');
addIframe.setAttribute('name', 'sample-iframe');
addIframe.style.height = height ? height : "360px";
addIframe.style.width = width ? width : "360px";
parentElm.appendChild(addIframe)
// make an post request
var form, input;
form = document.createElement("form");
form.action = 'example.com';
form.method = "post";
form.target = "sample-iframe";
Object.keys(allParams).forEach(function (elm) {
console.log('elm: ', elm, allParams[elm]);
input = document.createElement("input");
input.name = elm;
input.value = allParams[elm];
input.type = "hidden";
form.appendChild(input);
})
parentElm.appendChild(form);
form.submit();

Resources