I have the following problem, I need to disable the native Keyboard completely. The keyboard should only show when I call the show() and hide when I call the close() function (this will be on a Button for the user to toggle the Keyboard).
The Keyboard showing on clicking the Field and on Focus needs to be completely disabled.
On Stackoverflow I found this:
InputMethodManager im = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(editText.getWindowToken(), 0);
So my thought was In the "Init"(Line 52 in the IonicKeyboard.java) I need to change it.
if ("init".equals(action)) {
cordova.getThreadPool().execute(new Runnable() {
public void run() {
//new Logic on init
View v = cordova.getActivity().getCurrentFocus();
((InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
DisplayMetrics dm = new DisplayMetrics();
cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
final float density = dm.density;
//http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing
final View rootView = cordova.getActivity().getWindow().getDecorView().findViewById(android.R.id.content).getRootView();
OnGlobalLayoutListener list = new OnGlobalLayoutListener() {
int previousHeightDiff = 0;
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
rootView.getWindowVisibleDisplayFrame(r);
PluginResult result;
int heightDiff = rootView.getRootView().getHeight() - r.bottom;
int pixelHeightDiff = (int)(heightDiff / density);
if (pixelHeightDiff > 100 && pixelHeightDiff != previousHeightDiff) { // if more than 100 pixels, its probably a keyboard...
String msg = "S" + Integer.toString(pixelHeightDiff);
result = new PluginResult(PluginResult.Status.OK, msg);
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
}
else if ( pixelHeightDiff != previousHeightDiff && ( previousHeightDiff - pixelHeightDiff ) > 100 ){
String msg = "H";
result = new PluginResult(PluginResult.Status.OK, msg);
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
}
previousHeightDiff = pixelHeightDiff;
}
};
rootView.getViewTreeObserver().addOnGlobalLayoutListener(list);
PluginResult dataResult = new PluginResult(PluginResult.Status.OK);
dataResult.setKeepCallback(true);
callbackContext.sendPluginResult(dataResult);
}
});
return true;
}
return false; // Returning false results in a "MethodNotFound" error.
}
Sadly this does not work at all...
I think I have to change the close / show function too but I am not really sure what the correct code is, and I dont know if this change would affect other Keyboard behaviour. (But I basically need Focus without Keyboard)
I also found this Cordova Plugin
which looks very promising, but I decided to change this in the Ionic Keyboard Plugin, because I need the same behaviour in Windows too.
Very glad if someone could help me out here.
Regards Christopher
This can be accomplished by disabling all inputs with ng-disabled and later showing the keyboard with the Ionic Keyboard Plugin.
If you do not want the inputs to appear differently when disabled, you can override this style with CSS using the :disabled selector.
Hide on load:
<input ng-disabled="hideKeyboard">
hideKeyboard = true;
Show on function:
<input ng-disabled="hideKeyboard">
function showKeyboard(){
hideKeyboard = false;
cordova.plugins.Keyboard.show();
}
Related
I have two versions of code. The first version doesn't work, the second version does. Why does the first version's ainteger setting not work right? It is suppose to cause "Player One" and "Player Two" to be displayed above the buttons on the second register button press. I have included the code below.
To be more specific the program is supposed to call the server's register function when the register button is pressed. The server sets the value in the html, using the server's setinteger() when its integer value is one. When the client's ainteger is two (second time register key was pressed,) the event handler will call the server's printthename() function. This in turn calls the client's printname() and printname2() and displays the names. These names are not being displayed!
By tracing the error, when the button is hit twice , the register button event is not breaking in the register buttons event handler, and the block for the ainteger does not seem to be calling the printthename(). It does however show up in the server's register function when the server's integer value is one.
The program uses SignalR and two explorer tabs with Visual Studio 2019.
I have tried changing the code, slimmed it down, made it simple, and traced. And printthename() called from setinteger() is a version that works.
The GitHub link is : https://github.com/Joshei/signalr1
Branch 3 : new version, works.
Branch 4 : old version, doesn't work (doesn't display the names.)
The Visual Studio version has comments to explain that there is no way this is causing any problems.
/////////////////////////////////////HUB://///////////////////////////////////
public class ChatHub : Hub
{
private static readonly List<clients> ClientList = new List<clients>();
public void printthename()
{
string name = "";
if (whoseturn == 0)
{
name = "Player one ";
Clients.Client(ClientList[0].ConnectionId).printname(name);
name = "Player two ";
Clients.Client(ClientList[1].ConnectionId).printname2(name);
}
}
public void register(string name1)
{
clients A_Client = new clients();
A_Client.ConnectionId = Context.ConnectionId;
A_Client.Name = name1;
ClientList.Add(A_Client);
if (integer == 0)
{
integer = integer + 1;
}
else if (integer == 1)
{
Clients.Client(ClientList[1].ConnectionId).setinteger();
Clients.Client(ClientList[0].ConnectionId).setinteger();
}
}
}
/////////////////////////////////////HTML CLIENT://///////////////////////////////////
$(function () {
var ainteger = "0";
$("#Join").click(function () {
$('#Join').hide();
$('#Name').hide();
chat.server.register("a");
if (ainteger == "1") {
chat.server.printthename();
}
});
chat.client.setinteger = function () {
ainteger = "1";
};
});
Thank you, I have been trying to get this working since November 30.
I have a question to ask regarding vis.js popup option. Currently I am trying to implement it in react style so I was using https://github.com/crubier/react-graph-vis/tree/master/example as a starting point.
I realized that in src\index.js file I can add events array since I realize the select option is in there. However, when I do the following:
const events = {
select: function(event) {
var { nodes, edges } = event;
console.log("Selected nodes:");
console.log(nodes);
console.log("Selected edges:");
console.log(edges);
},
showPopup: function(event) {
document.getElementById('root').innerHTML = '<h2>showPopup event</h2>'+ JSON.stringify(params, null, 4);
}
};
I am not able to trigger the popup even at all. Inside the lib\index.js, I noticed that the code is supposed to loop over the events array:
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = Object.keys(events)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var _eventName = _step2.value;
this.Network.on(_eventName, events[_eventName]);
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
and I checked that vis.js has the popup option according to the documentation which can be found here: http://visjs.org/docs/network/
I am currently stuck on figuring out how to trigger the popup. There is a requirement to use react since the application will be based on it. It would be great if someone can point out what I did wrong.
Thanks in advance. XD
NOTE: This question is in regards to the github project that I am trying to build on top of. Therefore it is a little different because I am not taking a barebone vis.js
You are mixing things up. showPopup is an event, a function that is called when the popup is shown. You do not call it to show the popup.
To show the popup you simply hover over a node that has a title property.
Check out this fiddle I made (is in pure JS though): http://jsfiddle.net/56t9c0t4/
I am in a fix. I am not able to identify a way to capture the keyboard show/hide status on a mobile device browser.
Problem :
I have a popup on a form in which a Text Field is present. When the user taps on the text field the keyboard shows up pushing the popup on the form and eventually making the text field invisible.
Is there a way to identify the key board show/hide status???
No, there is no way to reliably know when a keyboard is showing. The one level of control you do have is you can set your app to pan or resize when the keyboard shows up. If you set it to resize, it will recalculate your layout and shrink things so if fits the remaining screen. If you choose pan, it will keep the same size and just slide up the entire app.
you can find out keyboard show/hide inside your application,Try following code inside oncreate method,and pass your parent layout to view.
final View activityRootView = rellayLoginParent;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
Rect r = new Rect();
// r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
//MyLog.w("height difference is", "" + heightDiff);
if (heightDiff > 100)
{ // if more than 100 pixels, its probably a keyboard...
if(lytAppHeader.getVisibility() == View.VISIBLE)
{
lytAppHeader.setVisibility(View.GONE);
}
}
else
{
if(lytAppHeader.getVisibility() == View.GONE)
{
lytAppHeader.setVisibility(View.VISIBLE);
}
}
}
});
It seems there is no reliable way to do this in the browser. The closest I have come is to listen for focus events and then temporarily listen for resize events. If a resize occurs in the next < 1 second, it's very likely that the keyboard is up.
Apologies for the jQuery...
onDocumentReady = function() {
var $document = $(document);
var $window = $(window);
var initialHeight = window.outerHeight;
var currentHeight = initialHeight;
// Listen to all future text inputs
// If it's a focus, listen for a resize.
$document.on("focus.keyboard", "input[type='text'],textarea", function(event) {
// If there is a resize immediately after, we assume the keyboard is in.
$window.on("resize.keyboard", function() {
$window.off("resize.keyboard");
currentHeight = window.outerHeight;
if (currentHeight < initialHeight) {
window.isKeyboardIn = true;
}
});
// Only listen for half a second.
setTimeout($window.off.bind($window, "resize.keyboard"), 500);
});
// On blur, check whether the screen has returned to normal
$document.on("blur.keyboard", "input[type="text"],textarea", function() {
if (window.isKeyboardIn) {
setTimeout(function() {
currentHeight = window.outerHeight;
if (currentHeight === initialHeight) {
window.isKeyboardIn = false;
}, 500);
}
});
};
How can I split the content of a HTML file in screen-sized chunks to "paginate" it in a WebKit browser?
Each "page" should show a complete amount of text. This means that a line of text must not be cut in half in the top or bottom border of the screen.
Edit
This question was originally tagged "Android" as my intent is to build an Android ePub reader. However, it appears that the solution can be implemented just with JavaScript and CSS so I broadened the scope of the question to make it platform-independent.
Building on Dan's answer here is my solution for this problem, with which I was struggling myself until just now. (this JS works on iOS Webkit, no guarantees for android, but please let me know the results)
var desiredHeight;
var desiredWidth;
var bodyID = document.getElementsByTagName('body')[0];
totalHeight = bodyID.offsetHeight;
pageCount = Math.floor(totalHeight/desiredHeight) + 1;
bodyID.style.padding = 10; //(optional) prevents clipped letters around the edges
bodyID.style.width = desiredWidth * pageCount;
bodyID.style.height = desiredHeight;
bodyID.style.WebkitColumnCount = pageCount;
Hope this helps...
Speaking from experience, expect to put a lot of time into this, even for a barebones viewer. An ePub reader was actually first big project I took on when I started learning C#, but the ePub standard is definitely pretty complex.
You can find the latest version of the spec for ePub here:
http://www.idpf.org/specs.htm
which includes the OPS (Open Publication Structure), OPF (Open Packaging Format), and OCF (OEBPS Container Format).
Also, if it helps you at all, here is a link to the C# source code of the project I started on:
https://www.dropbox.com/sh/50kxcr29831t854/MDITIklW3I/ePub%20Test.zip
It's not fleshed out at all; I haven't played with this for months, but if I remember correctly, just stick an ePub in the debug directory, and when you run the program just type some part of the name (e.g. Under the Dome, just type "dome") and it will display the details of the book.
I had it working correctly for a few books, but any eBooks from Google Books broke it completely. They have a completely bizarre implementation of ePub (to me, at least) compared to books from other sources.
Anyway, hopefully some of the structural code in there might help you out!
I've had to code something like this too, and my (working) solution is this:
You have to apply these lines to the webview...
webView_.getSettings().setUseWideViewPort(true);
webView_.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);
Also, you have to inject some javascript. I've had tons of problems with the differents scales of my activity and the content rendered in the webview, so my solution doesn't take any kind of value from "outside".
webView_.setWebViewClient(new WebViewClient(){
public void onPageFinished(WebView view, String url) {
injectJavascript();
}
});
[...]
public void injectJavascript() {
String js = "javascript:function initialize() { " +
"var d = document.getElementsByTagName('body')[0];" +
"var ourH = window.innerHeight; " +
"var ourW = window.innerWidth; " +
"var fullH = d.offsetHeight; " +
"var pageCount = Math.floor(fullH/ourH)+1;" +
"var currentPage = 0; " +
"var newW = pageCount*ourW; " +
"d.style.height = ourH+'px';" +
"d.style.width = newW+'px';" +
"d.style.webkitColumnGap = '2px'; " +
"d.style.margin = 0; " +
"d.style.webkitColumnCount = pageCount;" +
"}";
webView_.loadUrl(js);
webView_.loadUrl("javascript:initialize()");
}
Enjoy :)
I recently attempted something similar to this and added some CSS styling to change the layout to horizontal instead of vertical. This gave me the desired effect without having to modify the content of the Epub in any way.
This code should work.
mWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
// Column Count is just the number of 'screens' of text. Add one for partial 'screens'
int columnCount = Math.floor(view.getHeight() / view.getWidth())+1;
// Must be expressed as a percentage. If not set then the WebView will not stretch to give the desired effect.
int columnWidth = columnCount * 100;
String js = "var d = document.getElementsByTagName('body')[0];" +
"d.style.WebkitColumnCount=" + columnCount + ";" +
"d.style.WebkitColumnWidth='" + columnWidth + "%';";
mWebView.loadUrl("javascript:(function(){" + js + "})()");
}
});
mWebView.loadUrl("file:///android_asset/chapter.xml");
So, basically you're injecting JavaScript to change the styling of the body element after the chapter has been loaded (very important). The only downfall to this approach is when you have images in the content the calculated column count goes askew. It shouldn't be too hard to fix though. My attempt was going to be injecting some JavaScript to add width and height attributes to all images in the DOM that don't have any.
Hope it helps.
-Dan
I was able to improve Nacho's solution to get horizontal swipe paging effect with WebView. You can find solution here and example code.
Edit:
Solution code.
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
wv = (HorizontalWebView) findViewById(R.id.web_view);
wv.getSettings().setJavaScriptEnabled(true);
wv.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
injectJavascript();
}
});
wv.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
int pageCount = Integer.parseInt(message);
wv.setPageCount(pageCount);
result.confirm();
return true;
}
});
wv.loadUrl("file:///android_asset/ch03.html"); // now it will not fail here
}
private void injectJavascript() {
String js = "function initialize(){\n" +
" var d = document.getElementsByTagName('body')[0];\n" +
" var ourH = window.innerHeight;\n" +
" var ourW = window.innerWidth;\n" +
" var fullH = d.offsetHeight;\n" +
" var pageCount = Math.floor(fullH/ourH)+1;\n" +
" var currentPage = 0;\n" +
" var newW = pageCount*ourW;\n" +
" d.style.height = ourH+'px';\n" +
" d.style.width = newW+'px';\n" +
" d.style.margin = 0;\n" +
" d.style.webkitColumnCount = pageCount;\n" +
" return pageCount;\n" +
"}";
wv.loadUrl("javascript:" + js);
wv.loadUrl("javascript:alert(initialize())");
}
In my WebChromeClient's onJsAlert get the number of horizontal pages which i pass to the custom HorizontalWebView to implement paging effect
HorizontalWebView.java
public class HorizontalWebView extends WebView {
private float x1 = -1;
private int pageCount = 0;
public HorizontalWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
float x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > 100) {
// Left to Right swipe action
if (x2 > x1) {
turnPageLeft();
return true;
}
// Right to left swipe action
else {
turnPageRight();
return true;
}
}
break;
}
return true;
}
private int current_x = 0;
private void turnPageLeft() {
if (getCurrentPage() > 0) {
int scrollX = getPrevPagePosition();
loadAnimation(scrollX);
current_x = scrollX;
scrollTo(scrollX, 0);
}
}
private int getPrevPagePosition() {
int prevPage = getCurrentPage() - 1;
return (int) Math.ceil(prevPage * this.getMeasuredWidth());
}
private void turnPageRight() {
if (getCurrentPage() < pageCount - 1) {
int scrollX = getNextPagePosition();
loadAnimation(scrollX);
current_x = scrollX;
scrollTo(scrollX, 0);
}
}
private void loadAnimation(int scrollX) {
ObjectAnimator anim = ObjectAnimator.ofInt(this, "scrollX",
current_x, scrollX);
anim.setDuration(500);
anim.setInterpolator(new LinearInterpolator());
anim.start();
}
private int getNextPagePosition() {
int nextPage = getCurrentPage() + 1;
return (int) Math.ceil(nextPage * this.getMeasuredWidth());
}
public int getCurrentPage() {
return (int) (Math.ceil((double) getScrollX() / this.getMeasuredWidth()));
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
}
Maybe it would work to use XSL-FO. This seems heavy for a mobile device, and maybe it's overkill, but it should work, and you wouldn't have to implement the complexities of good pagination (e.g. how do you make sure that each screen doesn't cut text in half) yourself.
The basic idea would be:
transform the XHTML (and other EPUB stuff) to XSL-FO using XSLT.
use an XSL-FO processor to render the XSL-FO into a paged format that you can display on the mobile device, such as PDF (can you display that?)
I don't know whether there is an XSL-FO processor available for Android. You could try Apache FOP. RenderX (XSL-FO processor) has the advantage of having a paged-HTML output option, but again I don't know if it could run on Android.
There is several ways this could be done. If every line is in its own element all you have to do is to check if one of it's edges goes outside of the view (either the browsers, or the "book page").
If you want to know how many "pages" there is going to be in advance, just temporary move them into the view and get what line a page ends. This could potentially be slow because of that page reflow is needed for the browser to know where anything is.
Otherwise I think that you could use the HTML5 canvas element to measure text and / or draw text.
Some info on that here:
https://developer.mozilla.org/en/Drawing_text_using_a_canvas
http://uupaa-js-spinoff.googlecode.com/svn/trunk/uupaa-excanvas.js/demo/8_2_canvas_measureText.html
Had this same problem recently and inspired by the answers found a plain CSS solution using CSS3's column-* attributes:
/* CSS */
.chapter {
width: 600px;
padding: 60px 10px;
-webkit-column-gap: 40px;
-webkit-column-width: 150px;
-webkit-column-count: 2;
height:400px;
}
/* HTML */
<div class="chapter">
your long lorem ipsum arbitrary HTML
</div>
The example above gives great results on a retina iPhone. Playing around with the different attributes yields in different spacing between the pages and such.
If you need to support multiple chapters for instance which need to start on new pages, there's an XCode 5 example on github: https://github.com/dmrschmidt/ios_uiwebview_pagination
You could split the pages in separate XHTML files and store them in a folder. Eg: page01, page02. You can then render those pages one by one underneath each other.
You can look at http://www.litres.ru/static/OR/or.html?data=/static/trials/00/42/47/00424722.gur.html&art=424722&user=0&trial=1 but the code may be heavily obfuscated, so just use Firebug to inspect DOM.
If the link isn't working, comment - would give you fixed.
I built this incredibly brilliant scrolling thumbnail image viewer for a client in Flash Actionscript 3. (Basically it just scrolls up or down depending on the mouse position). It works so so, (I can never get the percentages right so that it shows the top most image) but, that's beside the point. What is REALLY irking me is when I have the browser window open with my .swf loaded and I click on another app on my desktop, the stupid scrolling thumbnail area in the browser window starts to freak out.
"Where is my mouseY??!?!?!?" I assume it is thinking.
Is there a stage.Unfocus event I can tell my scrolling thumbnail area to STFU with?
I'd even consider writing some Javascript to call a flash function, if that's a preferred technique.
function checkMousePos(e:Event):void
{
if(mouseX < 145){
try{
var sHeight:int = MovieClip(root).stageHeight;
}catch(Error){
trace("stage not loaded");
}
if(mouseY > (sHeight/2) + 100){
if(tHolder.y-50 > - (compHeight-sHeight)){
Tweener.addTween(tHolder, {y:tHolder.y - 90, time:1,transition:"easeOutCubic"});
}
}else if(mouseY < (sHeight/2) - 100){
if(tHolder.y+50 < 80){
Tweener.addTween(tHolder, {y:tHolder.y + 90, time:1,transition:"easeOutCubic"});
}else{
Tweener.addTween(tHolder, {y:80, time:1,transition:"easeOutCubic"});
}
}
}
}
I suggest detecting the window focus events onblur and onfocus ( http://www.devguru.com/technologies/ecmascript/quickref/evHan_onBlur.html ) in Javascript then sending an enable / disable call through to the SWF file using ExternalInterface ( http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/external/ExternalInterface.html ) So inside your HTML you might have something like this (assuming swfobject here, but this isn't necessary http://code.google.com/p/swfobject/ ):
swfobject.embedSWF("mySWF", "mySWFId", swfWidth, swfHeight, "10.0.0", "", flashvars, params, attributes);
window.onblur=function () {
if ( document.getElementById("mySWFId").disableMouseScrolling) {
document.getElementById("mySWFId").disableMouseScrolling();
}
}
window.onfocus=function () {
if ( document.getElementById("mySWFId").enableMouseScrolling ) {
document.getElementById("mySWFId").enableMouseScrolling();
}
}
And inside your SWF file some equivalent ExternalInterface code to hook up the methods:
public class MyApplication extends ...
{
public function MyApplication ():void
{
ExternalInterface.addCallback("disableMouseScrolling", disableMouseScrolling);
ExternalInterface.addCallback("disableMouseScrolling", enableMouseScrolling);
...
}
private function disableMouseScrolling ():void
{
}
private function enableMouseScrolling ():void
{
}
...
}
Hope this helps. I've used it with IE8, Firefox 3 and Crome 4.
Regards,
stage.addEventListener(Event.MOUSE_LEAVE, function(e:Event):void {});