tinymce IE11 (loosing focus - insertContent()) - tinymce

please have a look:
var mceBookmark;
function TbInsert(txt) {
ed = tinymce.activeEditor;
ed.selection.moveToBookmark(mceBookmark);
ed.insertContent(txt);
window.setTimeout(function() {$("#ed").tinymce().focus(); },200)
}
$('#myButton').on('mousedown', function() {mceBookmark = ed.selection.getBookmark(); });
Using tinymce 4.9.x but it's an old story: this code works fine except on IE(11).
$('#myButton') is a Button outside tinymce. By clicking it, IE looses focus and bookmark-position. insertContent() will allways push 'txt' on top of content.
I've also checked this to store bookmark-position:
setup: function (ed) {
ed.on('blur', function(e) {
//mceBookmark = ed.selection.getBookmark();
});
but this will force IE11 to crash.
What is the best practice to store and restore tinymce-bookmarks and how can i force incertContet() to push 'txt' at bookmark-position?
tnx!

Related

Change content before preview in TinyMCE 4

In TinyMCE 4, I want to change displayed contents before they are showed on preview popup windows. This change must not affect current contents in editor. Can we do that?
If it can't, I want to catch close event of preview windows. How to do that?
TinyMCE allows us to register callbacks via the property init_instance_callback
By using the BeforeExecCommand event, oddly not in current documentation, you can make changes prior to a command being executed. We can similarly use the ExecCommand event to make changes after the command is executed. The Preview Plugin triggers the mcePreview command. You can view the Editor command Identifiers here.
Putting that together you can add the following when initializing your TinyMCE. This will show "changed content" in the preview without making visible changes to the content within TinyMCE.
var preProssesInnerHtml;
tinymce.init({
//other things...
init_instance_callback: function (editor) {
editor.on('BeforeExecCommand', function (e) {
if (e.command == "mcePreview") {
//store content prior to changing.
preProssesInnerHtml = editor.getContent();
editor.setContent("changed content");
}
});
editor.on("ExecCommand", function (e) {
if (e.command == "mcePreview") {
//Restore initial content.
editor.setContent(preProssesInnerHtml);
}
});
}
}

How to enable auto focus on SAPUI5 input suggestion field

I'm currently developing a sapui5 mobile application and am using an sap.m.Input with suggestions bound by a model like this:
new Page('page', {
showNavButton: true,
content: [
new sap.m.Input({
id: "input",
type: 'Text',
showSuggestion: true,
suggestionItemSelected: function(event) {
event.getParameters().selectedItem.mProperties.text;
},
liveChange: function() {
// some stuff
}
})
]
});
The Model is created and bound like the following:
var model = new sap.ui.model.json.JSONModel();
// model is filled
sap.ui.getCore().byId('input').setModel(model);
sap.ui.getCore().byId('input').bindAggregation('suggestionItems', '/', new sap.ui.core.Item({
text: "{someField}"
}));
When I now click into the input field on a mobile device, kind of a new screen opens with a new input field, which the user has to manually focus again, what seems like a usability flaw to me.
Is there a nice possibility to enable auto focusing the input field on this new screen, so that the user doesn't has to do it again? Or can this screen be disabled at all on mobile devices?
sap.m.input doesn't seem to have a own method for focusing, or at least I'm not finding one - I already tried using jquery's .focus() on the new input field, but without success.
edit: for clarification, the suggestion works troublefree - only the absence of the auto focus on the appearing new screen is what bothers me.
Here is a workaround to "fix" this behavior: https://jsbin.com/lukozaq
Note 1: The above snippet relies on internal implementation of how the popup works. Use it with caution as there are currently no public APIs to access the corresponding internal controls.
Note 2: I put the word fix in quotes because it seems to be the intended behavior that the user has to click on the second input field explicitly, according to the comment in the source code:
Setting focus to DOM Element, which can open the on screen keyboard on mobile device, doesn't work consistently across devices. Therefore, setting focus to those elements are disabled on mobile devices and the keyboard should be opened by the user explicitly.
That comment is from the module sap.m.Dialog. On a mobile device, when the user clicks on the source input field, a stretched Dialog opens up as a "popup" which has the second input field in its sub header.
Please check the API documentation of sap.m.Input, it has a method focus. You can call:
this.byId("input").focus()
to set the focus into the input field.
Try this:
jQuery.sap.delayedCall(0, this, function() {
this.byId("input").focus()
});
About how to detect when the user presses the input field: maybe something like this? Only problem is that I think you probably don't know the id of the new input field which is shown.
var domId = this.byId("input").getId();
$( "#"+domId ).click(function() {
jQuery.sap.delayedCall(0, this, function() {
this.byId("input").focus()
});
});
I am pretty sure that the first piece of code is how to put focus on an input. I'm not sure about the second part, but it's something to try.
in onAfterRendering() do the below..
onAfterRendering : function() {
$('document').ready(function(){
sap.ui.getCore().byId('input').focus();
});
}
I didnĀ“t have the exactly same problem, but It was similiar.
My problem was that I needed focus into suggestion input when the view had been rendered. My solution was to put following code into "hanldeRouteMatched" function:
var myInput = this.byId("inputName");
var viewName = this.getView().getId();
var selector1 = viewName + "--inputName-inner";
var selector2 = viewName + "--inputName-popup-input-inner";
jQuery.sap.delayedCall(1000, this, function() {
myInput.focus();
if($("#" + selector1)){
$("#" + selector1).click();
jQuery.sap.delayedCall(500, this, function() {
if($("#" + selector2)){
$("#" + selector2).focus();
}
});
}
});
If you see that suggestion input catch focus, but It lose it after, or It never catched it, try increasing the time in delayedCalls. The needed time depends on your connection speed.

Check if TinyMCE 4.x is in Fullscreen Mode

Is there a way to check if TinyMCE is in fullscreen mode?
I would like to press 'Esc' to exit full screen mode butI also use 'Esc' to cancel editing. Hence I would like a way to first check if the editor is in fullscereen mode.
The fullscreen plugin fires an event, when its state changes:
var tinyOptions = {
plugins: [ 'fullscreen' ],
setup: function(editor) {
editor.on('FullscreenStateChanged', function(e) {
console.log('FullscreenStateChanged event', e);
});
}
};
This way you can track the state yourself.
When TinyMCE is in Fullscreen Mode "mce-fullscreen" class is appended to body tag.
So all you need to do is check for the existence of mce-fullscreen class.
if $('.mce-fullscreen').length{
// Do something here,the editor is in fullscreen mode
}
If you have access to the editor object:
editor.plugins.fullscreen.isFullscreen();
This way is quick and simple.
var catchFulscreen = function() {
if( $('.mce-fullscreen').length > 1){
console.log('Now the editor is on fullscreen mode');
}
}
setInterval(catchFulscreen, 100);
This code was tested on TinyMce 4.1.x
But I had wanted to know to access inited TinyMce Object. If the object can be access, much more better solution for catching fullscreen mode as event!

can't tap on item in google autocomplete list on mobile

I'm making a mobile-app using Phonegap and HTML. Now I'm using the google maps/places autocomplete feature. The problem is: if I run it in my browser on my computer everything works fine and I choose a suggestion to use out of the autocomplete list - if I deploy it on my mobile I still get suggestions but I'm not able to tap one. It seems the "suggestion-overlay" is just ignored and I can tap on the page. Is there a possibility to put focus on the list of suggestions or something that way ?
Hope someone can help me. Thanks in advance.
There is indeed a conflict with FastClick and PAC. I found that I needed to add the needsclick class to both the pac-item and all its children.
$(document).on({
'DOMNodeInserted': function() {
$('.pac-item, .pac-item span', this).addClass('needsclick');
}
}, '.pac-container');
There is currently a pull request on github, but this hasn't been merged yet.
However, you can simply use this patched version of fastclick.
The patch adds the excludeNode option which let's you exclude DOM nodes handled by fastclick via regex. This is how I used it to make google autocomplete work with fastclick:
FastClick.attach(document.body, {
excludeNode: '^pac-'
});
This reply may be too late. But might be helpful for others.
I had the same issue and after debugging for hours, I found out this issue was because of adding "FastClick" library. After removing this, it worked as usual.
So for having fastClick and google suggestions, I have added this code in geo autocomplete
jQuery.fn.addGeoComplete = function(e){
var input = this;
$(input).attr("autocomplete" , "off");
var id = input.attr("id");
$(input).on("keypress", function(e){
var input = this;
var defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(37.2555, -121.9245),
new google.maps.LatLng(37.2555, -121.9245));
var options = {
bounds: defaultBounds,
mapkey: "xxx"
};
//Fix for fastclick issue
var g_autocomplete = $("body > .pac-container").filter(":visible");
g_autocomplete.bind('DOMNodeInserted DOMNodeRemoved', function(event) {
$(".pac-item", this).addClass("needsclick");
});
//End of fix
autocomplete = new google.maps.places.Autocomplete(document.getElementById(id), options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
//Handle place selection
});
});
}
if you are using Framework 7, it has a custom implementation of FastClicks. Instead of the needsclick class, F7 has no-fastclick. The function below is how it is implemented in F7:
function targetNeedsFastClick(el) {
var $el = $(el);
if (el.nodeName.toLowerCase() === 'input' && el.type === 'file') return false;
if ($el.hasClass('no-fastclick') || $el.parents('.no-fastclick').length > 0) return false;
return true;
}
So as suggested in other comments, you will only have to add the .no-fastclick class to .pac-item and in all its children
I was having the same problem,
I realized what the problem was that probably the focusout event of pac-container happens before the tap event of the pac-item (only in phonegap built-in browser).
The only way I could solve this, is to add padding-bottom to the input when it is focused and change the top attribute of the pac-container, so that the pac-container resides within the borders of the input.
Therefore when user clicks on item in list the focusout event is not fired.
It's dirty, but it works
worked perfectly for me :
$(document).on({
'DOMNodeInserted': function() {
$('.pac-item, .pac-item span', this).addClass('needsclick');
}
}, '.pac-container');
Configuration: Cordova / iOS iphone 5

Mobile Safari: Disable scrolling pages "out of screen"

I want to block scrolling page "out of the iPhone screen" (when gray Safari's background behind the page border is visible). To do this, I'm cancelling touchmove event:
// Disables scrolling the page out of the screen.
function DisableTouchScrolling()
{
document.addEventListener("touchmove", function TouchHandler(e) { e.preventDefault(); }, true);
}
Unfortunately, this also disables mousemove event: when I tap on a button then move my finger out of it, then release the screen, the button's onclick event is triggered anyway.
I've tried mapping touch events on mouse events, as desribed here: http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/, but to no avail (the same behavior).
Any ideas?
From what I understand of your question, you've attempted to combine the code you've presented above with the code snippet provided by Ross Boucher on Posterous. Attempting to combine these two snippets back-to-back won't work, because in disabling touchmove, you've also disabled the shim that allows mousemove to work via his sample.
This question and its answers sketch out a workable solution to your problem. You should try these two snippets to see if they resolve your issue:
This snippet, which disables the old scrolling behavior:
elementYouWantToScroll.ontouchmove = function(e) {
e.stopPropagation();
};
Or this one, from the same:
document.ontouchmove = function(e) {
var target = e.currentTarget;
while(target) {
if(checkIfElementShouldScroll(target))
return;
target = target.parentNode;
}
e.preventDefault();
};
Then, drop in the code on Posterous:
function touchHandler(event)
{
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
{
case "touchstart": type = "mousedown"; break;
case "touchmove": type="mousemove"; break;
case "touchend": type="mouseup"; break;
default: return;
}
//initMouseEvent(type, canBubble, cancelable, view, clickCount,
// screenX, screenY, clientX, clientY, ctrlKey,
// altKey, shiftKey, metaKey, button, relatedTarget);
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY,
first.clientX, first.clientY, false,
false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
And that should do it for you. If it doesn't, something else isn't working with Mobile Safari.
Unfortunately I haven't had the time to check out to above yet but was working on an identical problem and found that the nesting of elements in the DOM and which relation you apply it to affects the handler a lot (guess the above solves that, too - 'var target = e.currentTarget').
I used a slightly different approach (I'd love feedback on) by basically using a class "locked" that I assign to every element which (including all its children) i don't want the site to scroll when someone touchmoves on it.
E.g. in HTML:
<header class="locked">...</header>
<div id="content">...</div>
<footer class="locked"></div>
Then I have an event-listener running on that class (excuse my lazy jquery-selector):
$('.ubq_locked').on('touchmove', function(e) {
e.preventDefault();
});
This works pretty well for me on iOs and Android and at least gives me the control to not attach the listener to an element which I know causes problems. You do need to watch your z-index values by the way.
Plus I only attach the listener if it is a touch-device, e.g. like this:
function has_touch() {
var isTouchPad = (/hp-tablet/gi).test(navigator.appVersion);
return 'ontouchstart' in window && !isTouchPad;
}
This way non-touch devices will not be affected.
If you don't want to spam your HTML you could of course just write the selectors into an array and run through those ontouchmove, but I would expect that to be more costly in terms of performance (my knowledge there is limited though). Hope this can help.