TinyMCE: j is undefined - javascript

What's wrong with this code? I get "J is undefined message" after insert the image. I think this happends while i try to close itself.
var ImageDialog =
{
init : function()
{
var f = document.forms[0], ed = tinyMCEPopup.editor;
e = ed.selection.getNode();
if (e.nodeName == 'IMG')
{
f.src.value = ed.dom.getAttrib(e, 'src');
}
},
update : function()
{
var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, args = {}, el;
tinyMCEPopup.restoreSelection();
if (f.src.value === '')
{
if (ed.selection.getNode().nodeName == 'IMG')
{
ed.dom.remove(ed.selection.getNode());
ed.execCommand('mceRepaint');
}
tinyMCEPopup.close();
return;
}
tinymce.extend(args,
{
src : f.src.value
});
el = ed.selection.getNode();
if (el && el.nodeName == 'IMG')
{
ed.dom.setAttribs(el, args);
tinyMCEPopup.editor.execCommand('mceRepaint');
tinyMCEPopup.editor.focus();
}
else
{
ed.execCommand('mceInsertContent', false, '<img src="'+args['src']+'" id="_mce_temp_rob" alt="" />', {skip_undo : 1});
ed.undoManager.add();
ed.focus();
ed.selection.select(ed.dom.select('#_mce_temp_rob')[0]);
ed.selection.collapse(0);
ed.dom.setAttrib('_mce_temp_rob', 'id', '');
tinyMCEPopup.storeSelection();
}
tinyMCEPopup.close();
},
getImageData : function()
{
var f = document.forms[0];
this.preloadImg = new Image();
this.preloadImg.src = tinyMCEPopup.editor.documentBaseURI.toAbsolute(f.src.value);
}
};
tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog);

it's a tinymce bug. Internally, the tinymce code uses a <span id="mce_marker"></span> to remember the caret-position when pasting. when validating the resulting fragment, after the paste, the span is deemed invalid and removed, thus breaking the code by removing the marker.
This issue will be fixed in the next official tinymce minor release. There are some workarounds for this kind of issue. One is to add to add id and mce-data-type attribute to spans as valid elements (init setting). Example:
// The valid_elements option defines which elements will remain in the edited text when the editor saves.
valid_elements: "#[id|class|title|style]," +
"a[name|href|target|title]," +
"#p,-ol,-ul,-li,br,img[src],-sub,-sup,-b,-i,-u" +
"-span[data-mce-type]",

Related

Detect if an element is deleted from Codemirror with backspace

When i delete the following "label" as a block using the backspace key, i would like to detect this event and do an ajax call, for example.
This part is deleted when i use backspace
Rendered
The problem is: there can be lots of labels (a tags) in textarea with different id's, i want to detect when any block is going to be deleted, save the id and remove.
Configuration
I'm using a custom configuration with a custom entity called annotation which represents the HTML above.
// Create CodeMirror (with lineWrapping on).
var codeMirror = CodeMirror(document.getElementById('firepad-container'), {lineWrapping: true});
// Create Firepad (with rich text toolbar and shortcuts enabled).
var firepad = Firepad.fromCodeMirror(firepadRef, codeMirror, {
richTextShortcuts: true,
richTextToolbar: true,
userId: userId,
userColor: userImage,
});
//// Create FirepadUserlist (with our userId, user name and avatar to display).
var firepadUserList = FirepadUserlist.fromDiv(firepadRef.child('users'),
document.getElementById('userlist'), userId, displayName, userImage);
firepad.registerEntity('annotation', {
render: function (info, entityHandler) {
var inputElement = document.createElement('a');
if(info.id) {
inputElement.setAttribute('id', info.id);
}
if(info.classList) {
inputElement.setAttribute('class', info.classList);
}
if(info.color || info.cursor) {
inputElement.setAttribute('style', 'color:' + info.color + '; cursor:' + info.cursor + ';');
}
inputElement.innerText = info.innerText;
inputElement.addEventListener('click', function(e){
editAnnotation(info.id, e);
entityHandler.remove();
});
return inputElement;
}.bind(this),
fromElement: function (element) {
var info = {};
if(element.hasAttribute('id')) {
info.id = element.id;
}
if(element.hasAttribute('class')) {
info.classList = element.classList;
}
info.color = element.style["color"];
info.cursor = element.style["cursor"];
info.innerText = element.innerText;
return info;
},
update: function (info, element, entityHandler) {
if(info.id) {
element.setAttribute('id', info.id);
}
if(info.classList) {
element.setAttribute('class', info.classList);
}
if(info.color || info.cursor) {
element.setAttribute('style', 'color:' + info.color + '; cursor:' + info.cursor + ';');
}
element.innerText = info.innerText;
},
export: function () {
var inputElement = document.createElement('a');
return inputElement;
}
});
If you want to add this new entity just use this:
firepad.insertEntity('annotation', { 'id': annotationId, 'color': color, 'cursor': 'pointer', 'innerText': 'whatever you want'});

how to fix TypeError: window.getComputedStyle(...) is null in firefox?

I am using zepto for drag and swap it works perfectly in chrome but showing error in firefox. Below is the section of the script of dragswap in which it is showing error. Please help. Thanks in advance
`; (function ($) {
$.fn.dragswap = function (options) {
var dragSrcEl;
function getPrefix() {
var el = document.createElement('p'),
getPre, transforms = {
'webkitAnimation': '-webkit-animation',
'OAnimation': '-o-animation',
'msAnimation': '-ms-animation',
'MozAnimation': '-moz-animation',
'animation': 'animation'
};
document.body.insertBefore(el, null);
for (var t in transforms) {
if (el.style[t] !== undefined) {
el.style[t] = "translate3d(1px,1px,1px)";
// if(window.getComputedStyle && (style = window.getComputedStyle(element, null)) !== null)
getPre = window.getComputedStyle(el).getPropertyValue(transforms[t]);
// return the successful prefix
return t;
}
}
document.body.removeChild(el);
}
Firefox has a bug in which if the element is "display: none" then window.getComputedStyles will return null.
The below is where I found this knowledge which fixed the error in my third-party code. Note In my case the element was also an iFrame
https://github.com/marcj/css-element-queries/issues/148

Transforming old code to ember component

currently i'm starting with Ember, and i'm loving it! I'm with some difficulties, especially when it comes to components.
For you to understand, I'm going through old code to Ember, and I would like to turn this code into a Component, but I do not know actually how to start, since I do not know how to catch the button being clicked, and I also realized that Ember has several helpers, maybe I do not need any of this giant code to do what I want.
This is the old code result: http://codepen.io/anon/pen/WQjobV?editors=110
var eventObj = {};
var eventInstances = {};
var actual;
var others;
var clicked;
var createEventInstance = function (obj) {
for (var key in obj) {
eventInstances[key] = new Event(obj[key]);
}
};
var returnStyle = function (inCommon) {
var $inCommon = inCommon;
$inCommon.css({
width: '342.4px',
minWidth: '342.4px'
});
$inCommon.find('.cta').removeClass('hidden');
$inCommon.find('.event-close').removeClass('inline');
$inCommon.find('.event-info_list').removeClass('inline');
$inCommon.removeClass('hidden');
$inCommon.find('.expanded').slideUp();
$inCommon.find('.expanded').slideUp();
$inCommon.find('.event-arrow').remove();
$inCommon.find('h2').find('ul').remove('ul');
};
var Event = function (id) {
this.id = id;
};
Event.prototype.expandForm = function () {
actual.css('width', '100%');
actual.find('.event-info_list').addClass('inline');
actual.find('.expanded').slideDown().css('display', 'block');
actual.find('.event-close').addClass('inline');
};
Event.prototype.close = function () {
returnStyle(actual);
returnStyle(others);
};
Event.prototype.hideElements = function () {
clicked.addClass('hidden');
others.addClass('hidden');
};
Event.prototype.maskPhone = function () {
$('[name$=phone]').mask('(99) 99999-9999', {
placeholder: '(00) 0000-0000'
});
};
$('.submit-form').on('click', function (e) {
e.preventDefault();
var id = '.' + $(this).data('id');
var name = $(id).children('#person-name').val();
var email = $(id).children('#person-email').val();
var guests = $(id).children('#person-obs.guests').val();
var phone = $(id).children('#person-phone').val();
var participants = $(id).children('#booking-participants').val();
if (name === '' || email === '' || phone === '' || participants === '' || guests === '') {
alert('Preencha os campos obrigatórios.');
} else {
$(id).submit();
}
});
Event.prototype.createDropDown = function () {
actual.find('h2').addClass('event-change')
.append('<span class="event-arrow" aria-hidden="true">â–¼</span>')
.append(function () {
var self = $(this);
var list = '<ul class="dropdown hidden">';
$('.event').each(function (index) {
if ($(this).find('h2')[0] != self[0]) {
list += '<li data-index="' + index + '">' + $(this).find('h2').text() + '</li>';
}
});
return list;
}).click(function () {
if ($(this).attr('data-expanded') == true) {
$(this).find('ul').toggleClass('hidden');
$(this).attr('data-expanded', false);
} else {
$(this).find('ul').toggleClass('hidden');
$(this).attr('data-expanded', true);
}
}).find('li').click(function (e) {
e.stopPropagation();
actual.find('.event-info_list').removeClass('inline');
actual.find('h2').attr('data-expanded', false);
actual.find('h2').removeClass('event-change');
actual.find('.expanded').slideUp().css('display', 'inline-block');
others.removeClass('hidden');
actual.find('.cta').removeClass('hidden');
actual.find('h2').find('.event-arrow').remove();
actual.find('h2').off('click');
actual.find('h2').find('ul').remove('ul');
$($('.event')[$(this).attr('data-index')]).find('.cta').trigger('click');
});
};
Event.prototype.open = function () {
actual = $('[data-id="' + this.id + '"]');
others = $('.event').not(actual);
clicked = actual.find('.cta');
this.hideElements();
this.expandForm();
this.createDropDown();
this.maskPhone();
};
$('.event').each(function (i, event) {
var prop = 'id' + $(event).data('id');
var value = $(event).data('id');
eventObj[prop] = value;
});
createEventInstance(eventObj);
Basically i have this boxes, which box represent one booking in some event (will be populate by the server). When the user clicks in one box, this boxes expands and the other disappear. But than a dropbox will be created with the other boxes, so the user can navigate in the events by this dropdown.
I didn't do much with Ember, i transform the "events" div into a component with the name "BookingBoxComponent" and two actions:
SiteApp.BookingBoxComponent = Ember.Component.extend({
actions:
open: function() {
// HOW COULD I ACCESS THE CLICKED BUTTON HERE?
},
close: function() {
}
});
As you can see, i put two actions, one for opening the box and other for closing, should i just put the logic in both, or i can improve this like a Ember way?
I don't know if i am asking to much here, so if i am, at least i would like to know how to access the button clicked in the open method, i was trying passing as a parameter, like:
<button {{action 'open' this}}></button>
But didn't work.
I could offer 50 of my points to someone who help transform the old cold in a Ember way code.
Thanks.
The event object will be passed with every action as the last parameter, so when you specified this you were actually passing whatever object has context in that block. In your open function, do not pass this and do
open: function(event) {
// event.currentTarget would be the button
}
And now you can do something like event.currentTarget or event.target

webkitmutationobserver does not work in Safari?

I need to monitor the display state of an element. I'm using the following code
if WebKitMutationObserver?
observer = new WebKitMutationObserver observerFunc
observer.observe el, {attributes:true}
else
el.addEventListener "DOMAttrModified",(event)->
wrapper.style.display = el.style.display
return
However this does not work in Safari.
Also, typing "WebKitMutationObserver" in developer tools immediate window in Chrome gives the output
function WebKitMutationObserver() { [native code] }
while in Safari (v 5.1.7), this gives an error with the message
"Can't find variable: WebKitMutationObserver"
Could it be that Safari does not support WebkitMutationObserver? And if so, is there an alternative which I could use for this?
The newest Safari (6.0) does include WebKitMutationObserver. For older Safari's, here's some code we have used that fakes a DOMAttrModified event when you use setAttribute or removeAttribute to change an attribute. Note that this doesn't work if the browser itself changes an attribute internally.
var win = window;
var doc = win.document;
var attrModifiedWorks = false;
var listener = function () { attrModifiedWorks = true; };
doc.documentElement.addEventListener("DOMAttrModified", listener, false);
doc.documentElement.setAttribute("___TEST___", true);
doc.documentElement.removeAttribute("___TEST___", true);
doc.documentElement.removeEventListener("DOMAttrModified", listener, false);
if (!attrModifiedWorks)
{
This.DOMAttrModifiedUnsupported = true;
win.HTMLElement.prototype.__setAttribute = win.HTMLElement.prototype.setAttribute;
win.HTMLElement.prototype.setAttribute = function fixDOMAttrModifiedSetAttr (attrName, newVal)
{
var prevVal = this.getAttribute(attrName);
this.__setAttribute(attrName, newVal);
newVal = this.getAttribute(attrName);
if (newVal != prevVal)
{
var evt = doc.createEvent("MutationEvent");
evt.initMutationEvent
( "DOMAttrModified"
, true
, false
, this
, prevVal || ""
, newVal || ""
, attrName
, (prevVal == null) ? win.MutationEvent.ADDITION : win.MutationEvent.MODIFICATION
);
this.dispatchEvent(evt);
}
}
win.HTMLElement.prototype.__removeAttribute = win.HTMLElement.prototype.removeAttribute;
win.HTMLElement.prototype.removeAttribute = function fixDOMAttrModifiedRemoveAttr (attrName)
{
var prevVal = this.getAttribute(attrName);
this.__removeAttribute(attrName);
var evt = doc.createEvent("MutationEvent");
evt.initMutationEvent("DOMAttrModified", true, false, this, prevVal, "", attrName, win.MutationEvent.REMOVAL);
this.dispatchEvent(evt);
}
}
}

Uncaught ReferenceError: X is not defined

This code is being used on a Chrome Extension.
When I call the "showOrHideYT()" function, I get a
"Uncaught ReferenceError: showOrHideYT is not defined | (anonymous
function) | onclick"
This code will search for youtube links in a page, and it will add a button (it's really a div with an event) next to the link to show the iframe with the embedded video, pretty much like Reddit Enhancement Suite. Consider the code, per se, incomplete. I just want to know what am i missing when i call the "showOrHideYT(frameZES12345)" function.
if needed, i can provide manifest.json.
Thanks
function showOrHideYT(id)
{
var YTvidWidth = 420;
var YTvidHeight = 315;
frameYT=getElementById(id);
console.log(frameYT.style.visibility);
if (frameYT.style.visibility == "hidden")
{
frameYT.style.width = YTvidWidth+"px";
frameYT.style.height = YTvidHeight+"px";
frameYT.style.visibility = "visible";
}
if (frameYT.style.visibility == "visible")
{
frameYT.style.width = "0px";
frameYT.style.height = "0px";
frameYT.style.visibility = "hidden";
}
};
// DOM utility functions
function insertAfter( referenceNode, newNode ) {
if ((typeof(referenceNode) == 'undefined') || (referenceNode == null)) {
console.log(arguments.callee.caller);
} else if ((typeof(referenceNode.parentNode) != 'undefined') && (typeof(referenceNode.nextSibling) != 'undefined')) {
if (referenceNode.parentNode == null) {
console.log(arguments.callee.caller);
} else {
referenceNode.parentNode.insertBefore( newNode, referenceNode.nextSibling );
}
}
};
function createElementWithID(elementType, id, classname) {
obj = document.createElement(elementType);
if (id != null) {
obj.setAttribute('id', id);
}
if ((typeof(classname) != 'undefined') && (classname != '')) {
obj.setAttribute('class', classname);
}
return obj;
};
///////////////////////////////////////
$(document).ready(function() {
var vidWidth = 420;
var vidHeight = 315;
var linksSemID = document.getElementsByTagName("a") ;
for (var i = 0; i < linksSemID.length; i++){
if (/id=$/.test(linksSemID[i].href)) links[i].href += "1";
}
i=0;
var youTubeRegExp = /(?:v=)([\w\-]+)/g;
var forEach = Array.prototype.forEach;
var linkArray = document.getElementsByTagName('a');
forEach.call(linkArray, function(link){
linkArray.id="zes" + i++;
var linkTarget = link.getAttribute('href');
if (linkTarget!=null)
{
if (linkTarget.search(youTubeRegExp) !=-1)
{
console.log (linkTarget);
idVideo=linkTarget.match(/(?:v=)([\w\-]+)/g);
//idVideo = idVideo.replace("v=", "");
//add buton
botaoMais = document.createElement('DIV');
botaoMais.setAttribute('class','expando-button collapsed video');
botaoMais.setAttribute('onclick','showOrHideYT(frameZES'+ i +')');
insertAfter(link, botaoMais);
//add iframe
ifrm = document.createElement('IFRAME');
ifrm.setAttribute('src', 'http://www.youtube.com/embed/'+ idVideo);
ifrm.style.width = '0px';
ifrm.style.height = '0px';
ifrm.style.frameborder='0px';
ifrm.style.visibility = 'hidden';
ifrm.setAttribute('id', 'frameZES' + i);
insertAfter(link, ifrm);
}
}
});
});
When you use setAttribute with a string, the event will be executed in the context of the page. The functions which are defined in a Content script are executed in a sandboxed scope. So, you have to pass a function reference, instead of a string:
Replace:
botaoMais.setAttribute('onclick','showOrHideYT(frameZES'+ i +')');
With:
botaoMais.addEventListener('click', (function(i) {
return function() {
showOrHideYT("frameZES"+ i);
};
})(i));
Explanation of code:
(function(i) { ..})(i) is used to preserve the value of i for each event.
Inside this self-invoking function, another function is returned, used as an event listener to click.
I see that you are using jQuery in your code. I personally think if we are using a library like jQuery, then we should not mix the native javascript code and jQuery code.
You can use jQuery bind to bind your the functions you need to call on dom ready.
Read below to know more.
suppose you want to call a javascript function on a button click, Here is the HTML for the same.
<div id="clickme">
<input id= "clickmebutton" type="button" value = "clickme" />
</div>
suppose "test" is the function you need to call, here is the code for test function.
function test() {
alert("hello");
}
you now need to bind the test function on the button click.
$(document).ready(function() {
$("#clickmebutton").bind("click", function(){
// do what ever you want to do here
test();
});
});

Categories