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.
Related
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!.
I have two pages. For explanations sake I'll call them page A and Page B. When I open page B in my browser it is rendered with all the styling and jquery ui code working properly, but when I open page B inside of a div in Page A via the load() method, the only thing that renders is the raw html, no styling, no interfaces. What is the problem? Directly below is the code from page B and all the way at the bottom is the code from page A:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script> //jquery ui
<link rel="stylesheet" href="http://spilot.koding.com/lbStyle.css"/> //stylesheet
<script src="http://www.parsecdn.com/js/parse-1.2.2.min.js"></script> //parse database
<script>
$(function(){
var crowd = ' ';
var ageGroup = ' ';
var activity = [];
var scene = [];
var neighborhood = [];
var date = [];
var details = [];
var time = [];
Parse.initialize("ivHLAO7z9ml1bBglUNuPSgcWabXe3UeE2yCgKM2x","gNeGt04lU7xcew893EvbEJ05qqc4POVhBsIBSCVj");
$(".menu").menu({
select: function (event, ui) {
$('.selected', this).removeClass('selected');
var selection = ui.item.addClass('selected').children('a').attr('name'); //add background color to selected menu item and get its attribute name
var choice = ui.item.text(); //get text of menu selection
if(selection == "ageGroup"){
$("#ageGroup").text(choice); //change the text in the first <a> of ageGroup menu to ageGroup selection.
ageGroup = $("#ageGroup").text();
}else{
crowd = selection;
};
} // closes select function
}); // closes menu
$("button").click(function(){
var city = JSON.parse( localStorage.getItem('city') );
var niche = Parse.Object.extend(crowd);
var query = new Parse.Query(niche);
query.equalTo("ageGroup", ageGroup);
query.equalTo("city", city);
//query.include([activity.date.details.location.neighborhood.time])
query.find({
success: function(results) {
for (i = 0; i < results.length; i++){
activity = results[i].get("activity");
scene = results[i].get("location");
neighborhood = results[i].get("neighborhood");
date = results[i].get("date");
details = results[i].get("details");
time = results[i].get("time");
};
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
//alert("working");
}); //closes click()
}); // close function()
</script>
<script>
$(function(){
$( "button" ).button();
});
</script>
</head>
<body>
<div id="div1">
<button>Button label</button>
<div id="div2">
<ul class="menu">
<li>
Age Group
<ul>
<li>18-21</li>
<li>21-30</li>
<li>30-40</li>
<li>40-50</li>
<li>50-60</li>
<li>60-70</li>
<li>70-80</li>
<li>80-90</li>
<li>90-100</li>
</ul>
</li>
</ul>
</div>
<div id="div3">
<ul class="menu" id="menu">
<li><img src="" alt="" /><h2>Academic: Art Studies</h2></li>
<li><img src="" alt="" /><h2>Academic: Literature</h2></li>
<li><img src="" alt="" /><h2>Academic: Social Sciences</h2></li>
<li><img src="" alt="" /><h2>Academic: Physical/Natural Sciences</h2></li>
</ul>
</div>
</div>
</body>
</html>
--------------//PAGE A//--------------
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script>
$(function(){
$("#mainDiv").load("http://myURl.com/find2.html"); //this is where I call load()
});
</script>
</head>
<body>
//this is the div where I want the other page to load
<div id="mainDiv">
</div>
</body>
</html>
since you are loading page "b" into page "a", you need to have all page "b" stylesheets/js in page "a" header.
please note that you are loading a complete html page into page "a", that includes html,header,body and that is not desirable, you should make page "b" a template that only contains the markup you need.
UPDATE:
you are embedding your scripts in the html, that is a bad practice, separate the JS code to different files.
When you include JS code in your file it will run as soon as the page loads, so if you put 'pageb' code in 'pagea' it will run as soon as 'pagea' was loaded and when you load 'pageb' the code will not run again.
You need to put 'pageb' code in a function and call it only after you loaded 'pageb' content.
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")
Below is the script used to display a attachment of a list item using web service.
<script type="text/javascript" src="/Test/js/SPAPI_Core.js"></script>
<script type="text/javascript" src="/Test/js/SPAPI_Lists.js"></script>
<script type="text/javascript">
function getAttachments(List,ID){
var lists = new SPAPI_Lists('Your File name');
var items = lists.getAttachmentCollection(List,ID);
if (items.status == 200){
var rows = items.responseXML.getElementsByTagName('Attachment');
var str="";
for (var i=0; i<rows.length; i++){
temp=rows[i].childNodes[0].nodeValue;
fileName=temp.substring(temp.lastIndexOf('/')+1);
str+=''+fileName+''+"<br />";
}
document.getElementById("att"+ID).innerHTML = str;
}else{
alert('There was an error: ' + items.statusText);
}
}
</script>
<xsl:if test="normalize-space(#Attachments) != '0'">
<div id="att{#ID}" style="padding: 10px;"></div>
<script type="text/javascript">
getAttachments("Posts",<xsl:value-of select="#ID"/>);
</script> </xsl:if>
reference URL: http://www.codeproject.com/Articles/31895/Displaying-Attachments-with-the-Data-View-Web-Part
The above script is used to display attachments... but no use...
please help me if im missing something
Thanks in advance
I followed instructions from your reference link and it worked.
This is what I did.
Downloaded SPAPI_Core and SPAPI_list hs files under siteassets/js folder.
dropped your script above in a content editor web part in the page.
Added your XSL Code above to my xsl file.
It worked. Just make sure to change your site path and list name.
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();