Show local HTML file with JavaScript in SWT Browser widget in RAP - swt

For my RAP-project I need to show some charts. Because I haven't found any widget for this purpose, my plan was to use the browser widget, so I can use JavaScript-Plugins like Highcharts or Chartsjs. But I can't get it working. If I set an HTML-File in browser.setUrl, the browser widget don't show anything, not even simple HTML. The JavaScript-Console in Chrome says
Not allowed to load local resource
If I enter the HTML-Code with the setText method it shows the HTML, but JavaScript is not working, it don't load external JS-File like the jQuery-library.
Can't this be done this way? Or where is my failure? (Sorry for my bad englisch, I'm not native speaker.)
Here's the Java-Code I tried:
browser = new Browser(composite, SWT.NONE);
browser.setTouchEnabled(true);
browser.setBounds(10, 10, 358, 200);
browser.setUrl("D:\\STATS\\statistiken.html");
Or this:
File file = new File("D:\\STATS\\statistiken.html");
browser = new Browser(composite, SWT.NONE);
browser.setTouchEnabled(true);
browser.setBounds(10, 10, 358, 200);
browser.setUrl(file.toURI().toString());
I tried also some other things, there were not working to.
With HTML in setText-method (I tried external libraries and local libraries in same folder):
browser = new Browser(composite, SWT.NONE);
browser.setBounds(10, 10, 358, 200);
browser.setText(
"<html>" +
"<head>" +
"<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js\"></script>" +
"<script src=\"http://code.highcharts.com/highcharts.js\"></script>" +
"<script src=\"http://code.highcharts.com/modules/exporting.js\"></script>" +
"</head>" +
"<body>" +
"<p>Test</p>" +
"<div id=\"container\" style=\"min-width: 400px; height: 400px; margin: 0 auto\"></div>" +
"</body>" +
"</htm>");
Hope someone can help me with this problem.

Local links will not be resolved and external links will not be loaded(Cross Domain problem) in your case.
I could suggest you 2 Solutions.
Solution 1:
This is useful when you have very few resources(html, javascript, css) to render on Browser and no Hyperlinks(which when cliked will load a different page).
You can use Velocity. Read this to start using Velocity.
You can have all the static content in Velocity Template and inject Dynamic content into it at Runtime.
Here is the excerpt from one of my Projects.
init.vm
<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
.transcript {
background-color: #d2d2d2;
}
.messageBlock {
margin-left: 4px;
margin-bottom: -15px;
}
.message {
margin-left: 115px;
word-wrap: break-word;
white-space: -moz-pre-wrap;
_white-space: pre;
white-space: pre-wrap;
}
</style>
</head>
<script type="text/javascript">
function resizeChatWindow() { var divT = document.getElementById("divTranscript"); divT.style.height = (document.body.clientHeight - getTopAreaHeight()) + "px"; divT.style.width = (document.body.clientWidth) + "px"; divT.style.overflow = "auto"; divT.style.position = "absolute"; divT.style.left = "0px"; divT.style.top = getTopAreaHeight() + "px";}
function getTopAreaHeight() { var chatAlert = document.getElementById("chatAlert"); if (chatAlert) { return chatAlert.clientHeight; } return document.getElementById("divBody").clientHeight;}
isChat=false; window.onresize=resizeChatWindow;
</script>
<script type="text/javascript">
$scriptText
</script>
<script type="text/javascript">
function addChat(chatText){
$("#divTranscript").append(chatText);
$("#divTranscript").animate({ scrollTop: $("#divTranscript")[0].scrollHeight }, "slow");
}
</script>
<body onload="resizeChatWindow();">
<div id="divBody"></div>
<div id="divTranscript">$history</div>
</body>
</html>
VelocityUtils
private void init() throws Exception {
ve = new VelocityEngine();
Properties velocityProperties = new Properties();
velocityProperties.put("resource.loader", "class");
velocityProperties.put("class.resource.loader.description", "Velocity Classpath Resource Loader");
velocityProperties.put("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
ve.init(velocityProperties);
//ve.init();
}
public String getInitHtml(String history) throws ResourceNotFoundException, ParseErrorException, Exception {
/* now render the template into a StringWriter */
StringWriter writer = null;
/* next, get the Template */
Template t = ve.getTemplate("templates/init.vm","UTF-8");
/* create a context and add data */
VelocityContext context = new VelocityContext();
String script = IOUtils.toString(VelocityUtils.class.getResourceAsStream("script/jquery.min.js"), "UTF-8");
context.put("scriptText", script); //You can even have all the script content in init.vm rather than injecting it at runtime.
context.put("history", StringUtils.defaultIfBlank(history, StringPool.BLANK));
writer = new StringWriter();
t.merge(context, writer);
/* show the World */
String returnMe = writer.toString();
return returnMe;
}
set the returned String in Browser.setText()
Solution 2:
I explained it here.

Related

INSERT INTO using Postgres on PYTHON DB-API

I'm trying to learn to add backend to a simple web app using postgreSQL and Python DB-API.
When running the app, why do I get an error if the function get_posts() in forumdb. python uses c. execute ("SELECT * FROM posts ORDER BY time;) instead of SELECT content, time FROM posts ORDER BY time;)?
Secondly, can anyone explain why c.execute("INSERT INTO posts VALUES (content)") doesn't work and we have to use the ('%s') % content thing in the function add_post(content) in forumdb.py?
Below is forum.py
from flask import Flask, request, redirect, url_for
# Using a module called forumdb
from forumdb import get_posts, add_post
app = Flask(__name__)
# HTML template for the forum page
HTML_WRAP = '''\
<!DOCTYPE html>
<html>
<head>
<title>DB Forum</title>
<style>
h1, form { text-align: center; }
textarea { width: 400px; height: 100px; }
div.post { border: 1px solid #999;
padding: 10px 10px;
margin: 10px 20%%; }
hr.postbound { width: 50%%; }
em.date { color: #999 }
</style>
</head>
<body>
<h1>DB Forum</h1>
<form method=post>
<div><textarea id="content" name="content"></textarea></div>
<div><button id="go" type="submit">Post message</button></div>
</form>
<!-- post content will go here -->
%s
</body>
</html>
'''
# HTML template for an individual comment
POST = '''\
<div class=post><em class=date>%s</em><br>%s</div>
'''
#app.route('/', methods=['GET'])
def main():
'''Main page of the forum.'''
posts = "".join(POST % (date, text) for text, date in get_posts())
html = HTML_WRAP % posts
return html
#app.route('/', methods=['POST'])
def post():
'''New post submission.'''
message = request.form['content']
add_post(message)
return redirect(url_for('main'))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
Below is forumdb.py
# "Database code" for the DB Forum.
import psycopg2
import datetime
def get_posts():
con = psycopg2.connect(dbname="forum")
c = con.cursor()
"""Return all posts from the 'database', most recent first."""
c.execute("SELECT content, time FROM posts ORDER BY time;")
return c.fetchall()
con.close()
def add_post(content):
con = psycopg2.connect(dbname="forum")
c = con.cursor()
"""Add a post to the 'database' with the current timestamp."""
c.execute("INSERT INTO posts VALUES ('%s')" % content)
con.commit()
con.close()
Thank you!
Because you are using  parameterized query is a query in which placeholders are used for parameters and the parameter values are supplied at execution time.
When we want to use a variable inside a SQL query you need to use a placeholder for it.
Example
query = """Update table set column_a = %s where column_b = %s"""

cross rider extension to fetch new posts from feed using google feeds api

I am trying to create an extension to display all the latest posts fetched from my feed using google feeds api. To implement this, I have added this code in background.js:
appAPI.ready(function() {
// Global variable to hold the toggle state of the button
var buttonState = true;
// Sets the initial browser icon
appAPI.browserAction.setResourceIcon('images/icon.png');
// Sets the tooltip for the button
appAPI.browserAction.setTitle('My Postreader Extension');
appAPI.browserAction.setPopup({
resourcePath:'html/popup.html',
height: 300,
width: 300
});});
and in popup.html,
<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript">
function crossriderMain($) {eval(appAPI.resources.get('script.js')); }</script>
</head>
<body><div id="feed"></div></body></html>
The script.js file is-
google.load("feeds", "1");
function initialize() {
var feed = new google.feeds.Feed("http://www.xxxxx.com/feed/");
feed.setNumEntries(10);
feed.load(function(result) {
if (!result.error) {
var container = document.getElementById("feed");
for (var i = 0; i < result.feed.entries.length; i++) {
var entry = result.feed.entries[i];
var div = document.createElement("div");
var link = document.createElement('a');
link.setAttribute('href', entry.link);
link.setAttribute('name', 'myanchor');
div.appendChild(document.createTextNode(entry.title));
div.appendChild(document.createElement('br'));
div.appendChild(link);
div.appendChild(document.createElement('br'));
container.appendChild(div);
}
}
});
}
google.setOnLoadCallback(initialize);
But I am unable to get desired result.The popup doesn't display anything.It just remain blank.
Since you are using a resource file for the popup's content, it's best to load the remote script from the crossriderMain function, as follows:
<!DOCTYPE html>
<html>
<head>
<!-- This meta tag is relevant only for IE -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript">
function crossriderMain($) {
appAPI.db.async.get('style-css', function(rules) {
$('<style type="text/css">').text(rules).appendTo('head');
});
appAPI.request.get({
url: 'http://www.google.com/jsapi',
onSuccess: function(code) {
$.globalEval(code);
appAPI.db.async.get('script-js', function(code) {
// runs in the context of the extension
$.globalEval(code.replace('CONTEXT','EXTN'));
// Alternatively, run in context of page DOM
$('<script type="text/javascript">').html(code.replace('CONTEXT','PAGE DOM')).appendTo('head');
});
}
});
}
</script>
</head>
<body>
<h1>Hello World</h1>
<div id="feed"></div>
</body>
</html>
[Disclaimer: I am a Crossrider employee]

How to save the SVG element to a static file with Dart?

I have to work with SVG elements using some DOM operation in Dart. After adding and changing some elements under the "svg" tag, I want to export the final SVG elements to a static file. Is there any API can do it?
Thanks!
You can use the download attribute on <a> elements. This tells the browser to download the resource instead of navigating to it.
You can get the contents of the SVG with innerHtml.
Here is an example.
First, the HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Svgtest</title>
<link rel="stylesheet" href="svgtest.css">
</head>
<body>
<h1>Svgtest</h1>
<div id="container">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="100" cy="50" r="40" stroke="black"
stroke-width="2" fill="red"/>
</svg>
</div>
<script type="application/dart" src="svgtest.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
Next, the Dart code:
import 'dart:html';
void main() {
Element container = query('#container');
String contents = container.innerHtml;
Blob blob = new Blob([contents]);
AnchorElement downloadLink = new AnchorElement(href: Url.createObjectUrlFromBlob(blob));
downloadLink.text = 'Download me';
downloadLink.download = 'svg_contents.svg';
Element body = query('body');
body.append(downloadLink);
}
Here is the browser coverage: http://caniuse.com/#feat=download At the time of this writing, Firefox, Chrome, and Opera support the download attribute.
(Note: there is no way to directly save a file to the native OS filesystem with HTML5.)
For IE 10+:
import 'dart:html';
import 'dart:js';
import "package:js/js.dart";
#JS("navigator.msSaveBlob")
external void msSaveBlob(blob, filename);
void main() {
Element container = query('#container');
String contents = container.innerHtml;
Blob blob = new Blob([contents]);
if (js.context['navigator']['msSaveBlob'] != null) {
msSaveBlob(blob, 'svg_contents.svg');
} else {
AnchorElement downloadLink = new AnchorElement(href: Url.createObjectUrlFromBlob(blob));
downloadLink.text = 'Download me';
downloadLink.download = 'svg_contents.svg';
Element body = query('body');
body.append(downloadLink);
}
}

Auto complete with multiple keywords

I want . Auto complete text box with multiple keyword. it's from database. if I use jQuery and do operation in client side mean. If the database size is huge, it leads to some issues. I need to know how this is done on the server side and get proper result.
I have already seen this topic but the operation is done on the client side. I need it from the database directly.
<html>
<head>
<title>Testing</title>
<link href="css/jquery-ui-1.10.3.custom.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.srchHilite { background: yellow; }
</style>
<script src="scripts/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="scripts/jquery-ui-1.10.3.custom.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
NewAuto();
});
function NewAuto() {
var availableTags = ["win the day", "win the heart of", "win the heart of someone"];
alert(availableTags); // alert = win the day,win the heart of,win the heart of someone
$("#tags").autocomplete({
source: function(requestObj, responseFunc) {
var matchArry = availableTags.slice(); // Copy the array
var srchTerms = $.trim(requestObj.term).split(/\s+/);
// For each search term, remove non-matches.
$.each(srchTerms, function(J, term) {
var regX = new RegExp(term, "i");
matchArry = $.map(matchArry, function(item) {
return regX.test(item) ? item : null;
});
});
// Return the match results.
responseFunc(matchArry);
},
open: function(event, ui) {
// This function provides no hooks to the results list, so we have to trust the selector, for now.
var resultsList = $("ul.ui-autocomplete > li.ui-menu-item > a");
var srchTerm = $.trim($("#tags").val()).split(/\s+/).join('|');
// Loop through the results list and highlight the terms.
resultsList.each(function() {
var jThis = $(this);
var regX = new RegExp('(' + srchTerm + ')', "ig");
var oldTxt = jThis.text();
jThis.html(oldTxt.replace(regX, '<span class="srchHilite">$1</span>'));
});
}
});
}
</script>
</head>
<body>
<div>
<label for="tags">
Multi-word search:
</label>
<input type="text" id="tags" />
</div>
</body>
</html>
take a look to Select2 it may help you.
Select2 is a jQuery based replacement for select boxes. It supports
searching, remote data sets, and infinite scrolling of results.
link
In your code, you have provided source as array. As you mentioned in comments, problem is how to get the data to source in jquery.
To make this work,
You need to do following
load jquery in header, which is you have already done.
Provid array,string or function for the source tag. [See api for
the source tag][1]
[1]: http://api.jqueryui.com/autocomplete/#option-source
In your serverside script, provid Jason encoded string.
If you check the API, you can see they have clear mentioned this.
Here is the jquery code
$(function() {
$( "#option_val" ).autocomplete({
dataType: "json",
source: 'search.php',
minLength: 1,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.value + " aka " + ui.item.id :
"Nothing selected, input was " + this.value );
}
});
});
</script>
Here is the php code, Sorry if you use differnt serverside script language.
<?php
// Create connection
$con=mysqli_connect("localhost","wordpress","password","wordpress");
// Check connection
if (mysqli_connect_errno($con))
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result=mysqli_query($con,"select * from wp_users");
while($row = mysqli_fetch_array($result))
{
$results[] = array('label' => $row['user_login']);
}
echo json_encode($results);
mysqli_close($con);
?>

Is it possible to create a 'view all' page in Tumblr?

I've tried creating pages using the 'standard layout' and 'custom layout' but neither allows the use of the {block:Posts} variable(s). I need to re-create essentially the archive page but with some custom css. Is there any way to accomplish this?
If I try $("#someDiv").load("/archive", "#content"); the whole page formatting gets screwed up. Is there a way to load just the <a> tags into a div on my custom page?
Or would it be possible to use the API entirely client side to accomplish this?
Any ideas on this would be appreciated.
I came up with two possible solutions if anyone else finds themselves stuck on this. I abandoned this first one before finalizing it, so it's a bit rough but a good start. It uses the API to load photos (that was all I needed) as you scroll down the page.
<script>
function getPhotos(offset){
$.ajax({
url: "http://api.tumblr.com/v2/blog/[tumblr].tumblr.com/posts?api_key=[key]&offset="+offset,
dataType: 'jsonp',
success: function(results){
loaded += 20;
total = results.response.blog.posts;
if(total > loaded){
results.response.posts.forEach(function(post){
post.photos.forEach(function(photo){
$("#photos ul").append("<li class='"+post.tags.join(" ")+"'><img src='"+photo.alt_sizes[0].url+"'></li>");
$("#photos").imagesLoaded(function(){
$("#photos").masonry({
itemSelector: 'li'
});
});
});
});
if($("#photos ul").height() < $(window).height()){
getPhotos(loaded);
}
}
}
});
}
loaded = 0;
getPhotos(loaded);
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
getPhotos(loaded);
}
});
</script>
What I've ended up doing is just using an iframe with a custom stylesheet appended to the head.
html:
<head>
<script src="http://[remote location]/frame.js"></script>
</head>
<body>
<div id="photos">
<iframe name="frame1" id="frame1" src="http://[tumblr]/archive" frameBorder="0"></iframe>
</div>
</body>
frame.js:
$(function(){
function insertCSS(){
var frm = frames['frame1'].document;
var otherhead = frm.getElementsByTagName("head")[0];
if(otherhead.length != 0){
var link = frm.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", "http://[remote location]/frame.css");
otherhead.appendChild(link);
setTimeout(function(){$("#frame1").show();}, 200);
clearInterval(cssInsertion);
}
}
cssInsertion = setInterval(insertCSS, 500);
//setTimeout(insertCSS, 1000);
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() > $(document).height() - 100 && $("#frame1").height() < 50000) {
$("#frame1").css("height", "+=1000px");
}
});
});
frame.css (stylesheet appended into iframe)
body{
overflow: hidden;
}
#nav_archive{
display: none;
}
.heading{
display: block !important;
}
.old_archive #content{
margin: 0 auto 0;
}
style.css (stylesheet on page where iframe is located)
#frame1{
border: none;
width: 100%;
height: 3000px;
overflow: hidden;
display: none;
}