I have to generate a popup in flutter that is coming from backend in the html, css and javascript form
In my case I'm using a korean based software named Band that is going to provide me google, fb and band login.
It's working is something like passport.js just in my case I've to use band but the issue is that when I try to render the response, the flutter is treating javascript as string.
Band developers guide link
Using band api I have got the response in html and javascript, something like given below
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="keywords" content="BAND" />
<meta name="description" content="밴드 방문을 환영합니다. 로그인하고 그룹 멤버들과 대화에 참여해 보세요." />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>로그인 | 밴드</title>
<script type="text/javascript">...</script>
</head>
<body>...</body>
</html>
Preview of response using postman software
Code snippet I'm using in flutter to render the response is given below
Future getJSONData() async
{
var redirectUri = Uri.encodeFull("apiredirection.php");
var response = await http.get(
Uri.encodeFull(
"https://auth.band.us/oauth2/authorize?redirect_uri={TEST_URL}" +
redirectUri),
headers: {"Accept": "application/text"});
this.setState(() {
data = response.body;
return data;
});
return data;
}
#override
Widget build(BuildContext context)
{
String html = data.toString();
return new MaterialApp(
home: new Scaffold(
body: new Container(
child: new HtmlView(
data: html),),),),
}
If the response that you need to display is in html String, you can use webview_flutter to render this on your app with a WebView.
// Let htmlData contain the html response
String htmlData = '''<!DOCTYPE html><html>...</html>''';
await webViewController.loadHtmlString(htmlData);
Then set webViewController as the WebViewController of your WebView.
Related
I have almost the same problem that in thread "Adobe PDF Embed API can not change the pdf" and "How to use a variable in Adobe's pdf embed API as URL-value?". which both were addressed by Mr Raymond Camden. The only difference is that I am trying to pass an url to location:url from Flask. Here's the code:
if(window.AdobeDC) displayPDF(urldata);
else document.addEventListener("adobe_dc_view_sdk.ready",
() => displayPDF(urldata));
function displayPDF(urldata) {
document.writeln(urldata[0]);
document.writeln(urldata[1]);
var myURL = urldata[0];
var myFileName = urldata[1];
adobeDCView.previewFile({
content: {
location: {
url: myURL,
},
},
metaData: {
fileName: myFileName
}
}, viewerConfig);
}
Note that I am using Mr Camden trick for dealing with
well-seasoned chicken and nice fresh eggs
.
I can get my 2 parameters going to the html file and to the js file. They are both writelined on the page from the displayPDF(urldata) function. Unfortunately they don't make it to content:location:url and metadata:filename. If I do hardcode these two parameters with existing PDF url and filename I get the result I want to obtain.
What am I doing wrong?
Thanks to anybody who could give me a clue.
All the best,
Pierre-Emmanuel FEGA
zepef#hotmail.com
I've found an answer to my own question. I have posted it on Adobe Community forum as well because "Passing value from external function to document function" because both responses from Shubhanshu Dixit and Raymond Camden have been of great help to me.
My goal was to open a PDF file coming from Azure Blob Storage to use it in an Azure Web App. The app is in Flask. Here's how I've done it and it works great on Azure as well as locally:
FLASK ROUTE
#app.route("/document", methods=['GET', 'POST'])
def document():
# Microsoft blob storage SAS token creation for accessing PDF file in blob storage
blob = get_blob_sas(BLOB_NAME_PATH, STORAGE_ACCOUNT_KEY, BLOB_CONTAINER_NAME, document_to_retrieve)
blob_url = 'https://'+BLOB_NAME_PATH+'.blob.core.windows.net/'+BLOB_CONTAINER_NAME+'/'+document_to_retrieve+'?'+blob
# URL and Filename parameters to send to Adobe Embed API
urldata = [blob_url, document_to_retrieve]
return render_template('view.html', title='SYSTRA Semantic Selected Document', urldata=urldata)
HTML PAGE
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta id="viewport" name="viewport" content="width=device-width, initial-scale=1"/>
<script type="text/javascript" src="{{ url_for('static', filename='view.js') }}"></script>
<script type="text/javascript">
varPDF = previewFile({{urldata|tojson}})
</script>
</head>
<body style="margin: 0px">
<div id="adobe-dc-view"></div>
<script type="text/javascript" src="https://documentcloud.adobe.com/view-sdk/main.js"></script>
</body>
</html>
JAVASCRIPT FUNCTIONS
function previewFile(urldata) {
var myURL = urldata[0];
var myFileName = urldata[1];
if(window.AdobeDC) displayPDF(myURL, myFileName);
else document.addEventListener("adobe_dc_view_sdk.ready",
() => displayPDF(myURL, myFileName));
}
function displayPDF(myURL, myFileName) {
document.write('displayPDF');
const viewerConfig = {
embedMode: "FULL_WINDOW",
defaultViewMode: "FIT_PAGE",
showLeftHandPanel: true,
showAnnotationTools: true,
showDownloadPDF: true,
showPrintPDF: true,
showPageControls: true,
showDisabledSaveButton: true,
downloadWithCredentials: true
};
var adobeDCView = new AdobeDC.View({
clientId: '<CLIENT_ID_KEY_HERE',
divId: "adobe-dc-view"
});
adobeDCView.previewFile({
content: {
location: {
url: myURL,
},
},
metaData: {
fileName: myFileName
}
}, viewerConfig);
}
I hope this helps.
All the best,
Pierre-Emmanuel
I am fetching a remote page's HTML and returning the HTML to review meta tags and I notice unexpected failed requests for all the remote assets in the other page's HTML whenever I assign that to a variable.
$.get(url, function(data, status) {
var dt = $(data);
}
By the time I've assigned that variable, it triggers all these remote requests.
How can I avoid the the fact that assigning this data to a variable in the DOM seems to trip a request for every image or resource on that remote page!
When you do $(data), jQuery ends up parsing the hTML and causes the requests to be made for the resources.
To get around it, use DOM parser so the resources are not fetched.
const myHTMLSource = `
<html>
<head>
<meta name="title" content="Foo Bar">
<meta name="description" content="FOO FOO">
<meta name="keywords" content="bar, egg, bacon">
<meta name="robots" content="index, follow">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="language" content="English">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"><\/script>
</head>
</body>
<h1>Test</h1>
<img src="http://placekitten.com/200/300" />
</body>
</html>`;
const parser = new DOMParser();
const testDoc = parser.parseFromString(myHTMLSource, "text/html")
const metaTags = testDoc.querySelectorAll("meta");
console.log(metaTags.length);
Since being asked how to use in in the jQuery Ajax request, it just uses data:
var request = $.ajax({
url: url,
method: "GET",
dataType: "text"
}).done(function( data ) {
const parser = new DOMParser();
const testDoc = parser.parseFromString(data, "text/html")
const metaTags = testDoc.querySelectorAll("meta");
console.log(metaTags.length);
}).fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});
So you claim: GETTING the html results in the requests inside the result are executed when doing $(data). So the issue is to NOT use $(data) but the raw HTML but that means some kind of split on </head> BEFORE creating a DOM fragment
Try this:
Uncomment the comments and remove the string I use for testing
//$.get(url, function(data, status) { // uncomment
// const dt = data.split("</head>")[0]
const fragment = document.createElement("div");
// fragment.innerHTML = dt;
// test
fragment.innerHTML = `<html>\n<head>\n<meta name="title" content="Foo Bar">\n<meta name="description" content="FOO FOO">\n<meta name="keywords" content="bar, egg, bacon">\n<meta name="robots" content="index, follow">\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n<meta name="language" content="English">\n<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"><\/script>`;
[...fragment.querySelectorAll("meta")]
.forEach(meta => {
console.log([...meta.attributes]
.map(attr => `${attr.nodeName}: ${attr.nodeValue}`))
})
//}}
My login ajax call is like this
$.get("LoginServlet", {'agileid': id, 'passwd': passwd, 'remember': 'yes' }, function(data) {
var results = JSON.parse(data);
if ( results.status == "failed") alert(data);
else window.location.href = 'Main.jsp';
});
My LoginServlet will set a session attribute special object which cannot be saved on the client side.
In Main.jsp, will determine existence of the session object and perform the necessary actions.
<%#page import="agile.px.myagiledashboard.listeners.SessionResourcesObject"%>
<%# page contentType="text/html;charset=UTF-8" session="false" %>
<!DOCTYPE html>
<%
HttpSession hSession = request.getSession();
System.out.println("Main.jsp: " + hSession.getId()); //This is to make sure the session is the same as in LoginServlet request
SessionResourcesObject SRO = (SessionResourcesObject) hSession.getAttribute("SRO");
String userName = "";
if ( SRO != null) {
try {
userName = SRO.getCUser();
System.out.println("main.jsp: " + userName);
} catch (Exception e) {
}
}
%>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
....
The code works with Chrome but when run in IE11 (in compatibility mode - company IT policy - can't change), the session object is always null after redirected to the jsp page.
Anyone one has the same problem? Or can anyone point out the problem(s) in my code and to fix this?
Thanks,
Alex
Strange enough: Using location.href solved the problem. Chrome does not behave differently , but in IE11 location.href will not create a new session but window.location.href will.
So I have a "discount" html page, where a user is prompted to enter a promo code, by using an Ajax GET request from the buttons OnClick, I am able to transfer this promo code to my spring controller, where I manipulate the data appropriately.
For some reason I am unable to "return" a new page from this controller, I do not get any noticeable errors on my server side but on my client side I get this error:
I am not sure if this is related or relevant.
I was wondering is my logic behind this flawed or am I not implementing the correct syntax to return a new page after the AJAX call.
Note: The AJAX request works fine as I am able to get a system.out.print to the console at the bottom of the controller with the relevant info. that I passed.
Here is my html code:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"></link>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript">
function myFunction(){
var code = document.getElementById("code").value;
var price = document.getElementById("price").value;
$.ajax({
type: "GET",
url: "/calculateDiscount",
data: {
code: code
}, // parameters
contentType: "application/json; charset=utf-8",
datatype: 'json'
//alert(status);
});
}
</script>
</head>
<body>
<div>
<center>
<h3>Total Price: $<text th:text="${totalPrice}" id="price"/> </h3>
<input type="text" name="firstname" id="code">
<button onclick="myFunction()">Calculate Discount</button>
<a style="color:blue" th:href="#{/welcome}">HomeScreen!</a>
<br />
<!-- <a style="color:blue" th:if="${myteam != null}" th:href="#{/leaveteam/{id}(id=${myteam?.id})}">Leave Team?!</a>
-->
</center>
</div>
</body>
</html>
Controller:
#RequestMapping(value="/calculateDiscount", method=RequestMethod.GET)
#ResponseBody
public String CalculateDiscount(Model model, #RequestParam("code") String code, RedirectAttributes redirectAttributes) {
///need to calculate price if codes correct then return page with card info then after proceed call purchasebooks controller!
System.out.println("Price: " + code );
Authentication loggedInUser = SecurityContextHolder.getContext().getAuthentication();
String email = loggedInUser.getName();
UserLogin user = uR.findByUserName(email);
int totalPrice = 0;
if (code.equals("Discount1010"))
{
Set<Book> books = user.getBooks();
for (Book b : books)
{
totalPrice = totalPrice + b.getPrice();
}
int discountPrice = (int) (totalPrice * .80);
model.addAttribute("totalPrice", totalPrice);
System.out.println("Price: " + discountPrice );
}
else {
Set<Book> books = user.getBooks();
for (Book b : books)
{
totalPrice = totalPrice + b.getPrice();
}
System.out.println("Price: " + totalPrice );
model.addAttribute("totalPrice", totalPrice);
}
return "payment";
}
The page I am trying to return:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<title>Insert title here</title>
</head>
<body>
<h3>Total Price: $<text th:text="${totalPrice}" id="price"/> </h3>
</body>
</html>
Any more info needed let me know.
K.
EDIT: In response to one of the answers below, I do have csrf disabled.
Here is my WebSecurityConfig class:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserLoginRepository userLoginRepository;
//http.authorizeRequests().antMatchers("/", "/home", "/registeruser").permitAll().antMatchers("/admin").hasRole("ADMIN")
#Autowired
DataSource dataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/home", "/registeruser").permitAll().antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll().and().logout()
.permitAll();
http.exceptionHandling().accessDeniedPage("/403");
http.csrf().disable();
//disable csrf to allow communication (we also dont need for this fyp as its not live)
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/fonts/**", "/images/**", "/css/**");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select user_name,password,user_status from user_login where user_name=?")
.authoritiesByUsernameQuery("select user_name, password from user_login where user_name=?");
}
#Bean
public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}
Update: #ResponseBody annotation was added to the controller method, problem still persists
I guess this is CSRF problem. You have Spring Security implemented (I can see
SecurityContexHolder class) and probably csrf enabled - this is default setting. If you want to disable it just use this
Java configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
XML:
<http>
<!-- ... -->
<csrf disabled="true"/>
</http>
But if you want to keep csrf enabled, you need to pass csrf token to ajax header. To do this, include csrf to meta tag:
<head>
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
And then include csrf to Ajax request:
var token = /*[[${_csrf.token}]]*/ '';
var header = /*[[${_csrf.headerName}]]*/ '';
$(document).ajaxSend(function(e,xhr,options) {
xhr.setRequestHeader(header, token);
});
The following is a JavaScript file that searches through YouTube video data using its API. Down at the bottom you'll see the onSearchResponse() function, which calls showResponse(), which in turn displays the search results.
As this code from Codecademy stands, a HUGE amount of information gets printed relating to my search term.
Instead of all that, can I simply display a hyperlink using the title and videoId attributes? How would I go about altering responseString in showResponse() to build that link? Thank you!
// Your use of the YouTube API must comply with the Terms of Service:
// https://developers.google.com/youtube/terms
// Helper function to display JavaScript value on HTML page.
function showResponse(response) {
var responseString = JSON.stringify(response, '', 2);
document.getElementById('response').innerHTML += responseString;
}
// Called automatically when JavaScript client library is loaded.
function onClientLoad() {
gapi.client.load('youtube', 'v3', onYouTubeApiLoad);
}
// Called automatically when YouTube API interface is loaded (see line 9).
function onYouTubeApiLoad() {
// This API key is intended for use only in this lesson.
// See link to get a key for your own applications.
gapi.client.setApiKey('AIzaSyCR5In4DZaTP6IEZQ0r1JceuvluJRzQNLE');
search();
}
function search() {
// Use the JavaScript client library to create a search.list() API call.
var request = gapi.client.youtube.search.list({
part: 'snippet',
q: 'clapton'
});
// Send the request to the API server,
// and invoke onSearchRepsonse() with the response.
request.execute(onSearchResponse);
}
// Called automatically with the response of the YouTube API request.
function onSearchResponse(response) {
showResponse(response);
console.log(response);
}
Here is the corresponding HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="stylesheets/styles.css">
<meta charset="UTF-8">
<title>My YouTube API Demo</title>
</head>
<body>
<section>
<div id="response"></div>
</section>
<script src="javascripts/search-2.js"></script>
<script src="https://apis.google.com/js/client.js?onload=onClientLoad" type="text/javascript"></script>
</body>
</html>
Your advice is much appreciated!
I think it might be what you are exactly trying to do.
function showResponse(response) {
var html = response.items.map(itemToHtml);
document.getElementById('response').innerHTML += html;
}
function itemToHtml(item) {
var title = item.snippet.title;
var vid = item.id.videoId;
return generateHyperlink(title, vid);
}
function generateHyperlink(title, vid) {
return '' + title + '<br/>';
}
This code show up links named title having YouTube video link using videoId.