TinyMCE : TypeError: this.getDoc(...) is undefined - tinymce-4

my question seems to be already ask, but truth me the situation here is diferent.
Problem:
TypeError: this.getDoc(...) is undefined
What i already do:
-update jquery version
-test every parameters pass to the tinymce functions, everything is ok
My code:
var html = '<div class="traduce-fields"><h4></h4><div class="text-block"><textarea class="textarea-tinymce" id="textarea-' + dataLang + '"></textarea></div><div class="bt-valide-traduce" onclick="sendTraduce($(this))"><p>TO TRADUCE !</p></div></div>';
$('.traduce-bloc-text').find('.traduce-inner').html(html);
//active de nouveau tinyMCE
tinymce.init({selector: '.textarea-tinymce'});
var selector = 'textarea-' + dataLang;
tinymce.get(selector).setContent('ok');

As mentioned in my original comment, my bet is that you are trying to use TinyMCE before its fully initialized. There is a function that can tell you when its fully initialized so you can use that to set the content:
tinymce.init({
selector: 'textarea',
...
setup: function (editor) {
editor.on('init', function () {
this.setContent('Using the on init stuff!');
});
}
As it takes you time to click on your alert this is probably allowing for TinyMCE to finish loading hence the setContent() call is then working.

My cod is long and show him in JS fiddle is hard but I got something that could help you:
This code works:
tinymce.init({selector: '.textarea-tinymce'});
alert(tinymce.get(idTextarea));
var tinyMCEInstance = tinymce.get(idTextarea);
tinyMCEInstance.setContent('ok');
This not:
tinymce.init({selector: '.textarea-tinymce'});
/*alert(tinymce.get(idTextarea));*/
var tinyMCEInstance = tinymce.get(idTextarea);
tinyMCEInstance.setContent('ok');
That's very strange, what kind of problem an alert could solve?
Thank you for helping me.

Related

Howto hook into 'PageLoaded' observer in SilverStripe 3?

I need to execute a jQuery function after a page loaded. The docs told me that it would be possible to hook into the 'PageLoaded' observer.
So I tried it like shown there. I put this function
Behaviour.register({
'#Form_ItemEditForm' : {
initialize : function() {
this.observeMethod('PageLoaded', this.pageLoaded);
this.observeMethod('BeforeSave', this.beforeSave);
this.pageLoaded(); // call pageload initially too.
},
pageLoaded : function() {
alert("You loaded a page");
},
beforeSave: function() {
alert("You clicked save");
}
}
});
into my cms.js which get's loaded in the backend. I tried it inside and outside (function($) { .. code ..}(jQuery)); and also inside the doucment.ready function inside the first function.
I always receive the same error in my console Uncaught ReferenceError: Behaviour is not defined.
Where is my mystake?
I believe you may have been looking at docs for 2.4, not 3.x
Version 3 and up are built using jQuery.entwine, where this from memory is old Prototype plugin stuff from 2.4, meaning of course that Behaviour is not defined, just as the error says.
The docs have recently been updated, so perhaps visit again, you might learn something new & much more helpful :)

Attaching jQuery plugins to Meteor template-generated DOM elements

According to the Meteor documentation, a callback assigned to Template.template_name.rendered will execute after each instance of template_name has finished rendering. I have been trying to use this feature to attach jQuery plugins (such as TagsManager or DotDotDot) to DOM elements generated by the templates. The "natural" way to do this would be something like:
Template.template_name.rendered = function () {
var template = this;
var elem = $('input#tags'+template.data._id);
elem.tagsManager(); // doesn't work
}
However, this does not work -- the expected behaviors do not come out attached to the element. The jQuery selector works properly and, by logging the internals of tagsManager(), I can see that the event handlers do seem to get attached, but after .tagsManager() finishes up, they are somehow unattached.
The "usual" solutions of wrapping the code in a $(document).ready or a short setTimeout suffer from the exact same behavior:
Template.template_name.rendered = function () {
var template = this;
$(document).ready(function () {
window.setTimeout(function () {
var elem = $('input#tags'+template.data._id);
elem.tagsManager();
}, 100); // 0.1 seconds + $(document).ready doesn't work
});
}
I only got it to work by giving an unrealistically high setTimeout time, such as 3 seconds:
Template.song.rendered = function () {
var template = this;
console.log("Template for "+template.data.title+" created");
$(document).ready(function () {
window.setTimeout(function () {
var elem = $('input#tags'+template.data._id);
elem.tagsManager();
}, 3000); // 3 seconds + $(document).ready works
});
}
As a matter of fact, even replacing elem.tagsManager() by a simple elem.on('click',...) suffers from the same behaviors as described above -- which is why the guys at Meteor have given us Template.template_name.events, I guess. However, this kind of breaks all interesting plugins, and forces us to rely on hacky, dangerous code such as the above. Is there a better way?
In the template, wrap the div you want to apply the jQuery with {{#constant}} helper. This will kill all reactivity you may have on elements wrapped up.
If you need reactivity or constant did not help, try this hack. I unbind the event of the element when rendered is called and bind it right after. The problem in this case is that rendered is called like a dozen times and it screw up some way I haven't figured out. Try debugging it to see how many it is called with console.log in the first line of rendered.
Hope it helps!
check that package : https://github.com/Rebolon/meteor-animation/blob/master/meteor-animation-client.js
line 38 to 56
it uses template.rendered with a cursor observer.
It might help you coz it also uses jquery.

Trying to catch hideDropdown event in TextExt.js

I am using TextExtJs for an autocomplete feature where you start typing and the dropdown of suggestions appears below the text input and you can select a suggested option with arrow keys or mouse.
Everything is working great except that I am trying to perform a function after the user selects one of the suggestions. There is a hideDropdown event which I think is the proper event to use for this. Unfortunately I'm not understanding how to do this, this is what I have tried:
$('#usearch').textext({
plugins : 'autocomplete ajax',
ajax : {
url : 'usersuggest.php',
dataType : 'json',
cacheResults : true
},
autocomplete : {
onHideDropdown : function(){
alert('A happened');
},
hideDropdown : function(){
alert('B happened');
}
},
onHideDropdown : function(){
alert('C happened');
},
hideDropdown : function(){
alert('D happened');
}
});
None of these functions with the alert actually ever run. They do not interfere with the suggestion piece of it. How do I attach a callback to this event?
I'm facing the same problem here....
Unfortunately there is no proper solution. The manual is as rudimental as the examples provided on the plugin page.
I managed to bind a kind of "onAddingTag" event, refer to this: http://textextjs.com/manual/plugins/tags.html#istagallowed
$('#textarea').textext().bind('isTagAllowed', function(e, data) {
var valueAdded = data.tag;
data.result = true; //needs to be done, since we're abusing this event
};
Despite the fact that this may help with this issue, your next problem would be: when does the user remove a tag?
Finally I ended up, using another autocomplete library.

Trigger.io + Angular.js and updating a view after calling forge.ajax

Having a problem, and so far couldn't get any solutions for seemingly similar SO questions to work. Problem is this:
Using Trigger.io's forge.ajax, my Angular.js view is not updated after the data is returned. I realize this is because forge.ajax is an asychronous function, and the data is returned after the view has already been displayed. I have tried to update the view by using $rootScope.apply(), but it doesn't work for me as shown in the many examples I have seen.
See the Controller code below:
function OfferListCtrl($scope) {
$scope.offers = [];
$scope.fetchOffers = function(callback) {
$scope.offers = [];
var successCallback = function(odataResults) {
var rawJsonData = JSON.parse(odataResults);
var offers = rawJsonData.d;
callback(offers);
};
var errorCallback = function (error){
alert("Failure:" + error.message);
};
forge.request.ajax({
type: 'GET',
url: 'https://www.example.com/ApplicationData.svc/Offers',
accepts: 'application/json;odata=verbose',
username: 'username',
password: 'password',
success: successCallback,
error: errorCallback
});
};
$scope.fetchOffers(function(offers) {
$scope.offers = offers;
forge.logging.info($scope.offers);
});
}
All the code there works fine, and $scope.offers gets populated with the Offer data from the database. The logging function shows the data is correct, and in the correct format.
I have tried using $rootScope.apply() in the logical places (and some illogical ones), but cannot get the view to update. If you have any ideas how I can get this to work, I would greatly appreciate it.
Edit: Added HTML
The HTML is below. Note the button with ng-click="refresh()". This is a just a workaround so I can at least see the data. It calls a one-line refresh function that executes $rootScope.apply(), which does update the view.
<div ng-controller="OfferListCtrl">
<h1>Offers</h1>
<ul>
<li ng-repeat="offer in offers">
<p>Description: {{offer.Description}}<br />
Id: {{offer.Id}}<br />
Created On: {{offer.CreatedOn}}<br />
Published: {{offer.Published}}<br />
</p>
</li>
</ul>
<input type="button" ng-click="refresh()" value="Refresh to show data" />
</div>
You need to change
$scope.fetchOffers(function(offers) {
$scope.$apply(function(){
$scope.offers = offers;
});
forge.logging.info($scope.offers);
});
It is because all changes to the $scope has to be made within the angular scope, in this case since you are calling ajax request using forge the callback is not executing within the angular framework, that is why it is not working.
You can use $scope.$apply() in this case to execute the code within angular framework.
Look at the $apply() methods doc
$apply() is used to execute an expression in angular from outside of
the angular framework. (For example from browser DOM events,
setTimeout, XHR or third party libraries). Because we are calling into
the angular framework we need to perform proper scope life-cycle of
exception handling, executing watches.
do this
function MyController($scope, myService)
{
myService.fetchOffers(data){
//assign your data here something like below or whateever
$offers = data
$scope.$apply();
}
});
Thanks
Dhiraj
When I do that I have an error like : "$digest already in progress"...
I'm Working with $q...
Someone knwo how I can resolve this issue ?
yes, this is caused where ur data comes fast enough and angular has not finished his rendering so the update cant update "outside" angular yet.
so use events:
http://bresleveloper.blogspot.co.il/2013/08/angularjs-and-ajax-angular-is-not.html

Run JS after rendering a meteor template

I have a template that looks something like this:
<template name="foo">
<textarea name="text">{{contents}}</textarea>
</template>
I render it with:
Template.foo = function() {
return Foos.find();
}
And I have some event handlers:
Template.foo.events = {
'blur textarea': blurHandler
}
What I want to do is set the rows attribute of the textarea depending on the size of its contents. I realize that I could write a Handlebars helper, but it wouldn't have access to the DOM element being rendered, which would force me to do some unnecessary duplication. What I want, ideally, is for meteor to trigger an event after an element is rendered. Something like:
Template.foo.events = {
'render textarea': sizeTextarea
}
Is this possible?
As of Meteor 0.4.0 it is possible to check if a template has finished rendering, see http://docs.meteor.com/#template_rendered
If I understand your question correctly, you should wrap your textarea resize code inside a Template.foo.onRendered function:
Template.foo.onRendered(function () {
this.attach_textarea();
})
I think the current 'best' way to do this (it's a bit of a hack) is to use Meteor.defer ala Callback after the DOM was updated in Meteor.js.
Geoff is one of the meteor devs, so his word is gospel :)
So in your case, you could do something like:
<textarea id="{{attach_textarea}}">....</textarea>
and
Template.foo.attach_textarea = function() {
if (!this.uuid) this.uuid = Meteor.uuid();
Meteor.defer(function() {
$('#' + this.uuid).whatever();
});
return this.uuid;
}
EDIT
Note, that as 0.4.0, you can do this in a much ad-hoc way (as pointed out by Sander):
Template.foo.rendered = function() {
$(this.find('textarea')).whatever();
}
Since about June 2014, the correct way to do this has been to set a callback using Template.myTemplate.onRendered() .
Yeah I think so - not sure if it's "the right way", but this works for me:
In your app JS, the client section will run whatever javascript there on the client. For example:
if (Meteor.is_client) {
$(function() {
$('textarea').attr('rows' , 12) // or whatever you need to do
})
...
Note the example here uses JQuery, in which case you need to provide this to the client (I think :-). In my case:
I created a /client dir, and added jquery.js file under this.
Hope this helps.

Resources