JavaScript widget code snippet on image onload - javascript

I'm working on a JavaScript widget (I actually have several I'd like to update) and hope to distill the embed code snippet down to just a single <img> tag with JavaScript in the onload attribute. In the past I used a along with an <img> tag. Then I switched to just a <script> tag to make the widget non-blocking. I'm working on the <img> only option for usability reasons. It is easier to copy and paste to move the widget around if you don't have to switch into the source view of the WYSIWYG editor. It is also really nice to have something you can visually see in a WYSIWYG editor.
Here's an example of the current draft of the snippet:
<img id='NotablePAD80' class='NotablePAD' src='//dev.notable.webapp.msu.edu/n.png'
data-section='nathanlounds' onload="(function(d){ var i=d.getElementsByTagName('IMG')[0],
u='https://dev.notable.webapp.msu.edu/n.js',
j=i.previousSibling||i; if(j.src!==u) { var s=d.createElement('SCRIPT');
s.type='text/javascript'; s.src=u; i.parentNode.insertBefore(s,i);}})(document);" />
What is the best way to prevent the widget from executing pre-save in the WYSIWYG? The loading of the widget can't change the DOM within the editor.
My ideas:
Look from the presence of the tinyMCE variable. Don't process
widget if it is defined. TinyMCE is an editor I'd need to be
compatible with. But I'd likely need 'fixes' for other WYSIWYG too.
Examine the DOM and look for properties that are
only present within a WYSIWYG, such as being inside an iframe. But I need the widget to work within iframes.
There are problems with both of those options. TinyMCE may not be defined yet when my widget executes. The image load event gets triggered multiple times for some reason. Ultimately I'd love a solution that would work universally.
Thoughts? Brilliant solutions?

Check if a parent of the image has contentEditable enabled, or if the body of the document is in designMode

Related

Summernote editor and script tags

I am building a web app which uses Summernote to allow for HTML editing.
Users are allowed to add and edit JavaScript as well, using inline <script> tags. This works fine and can be done in the editor's "Code View" mode.
What I'd like to do is, in the preview/WYSIWYG mode, instead of having the script being executed, just display an image (or text) to let the user know that there's a script there.
Something like:
I looked around and I don't think this has been done before. Is it possible? Any pointers on how I could accomplish this?
Thanks!
https://github.com/summernote/summernote/issues/495 explains how to do it using CSS only.

Programmatically insert images with the aloha editor

I want to include images in an aloha editable after a drop event, thus not using the toolbar button.
While some aloha commands may be executed programmatically, there is not so much doc about it and one must look into the code.
With the debugger i found that the relevant function is here so now i would go for copying the insertImg function body somewhere in my code and build my function.
On the other hand it would be much cleaner to reuse that code calling something like
Aloha.plugins.image.insertImg();
In a way similar to how it is done here. Is it possible to do such a thing?
A colleague explained me that there is nothing special required in order to insert an image. The function used by aloha is just a way to substitute jQuery and is not necessary.
Once the common/image plugin is loaded, it is sufficient to append an <img> tag inside the editable, also with jQuery, and the plugin will be triggered on it, adding the resize handle and showing the image toolbar when needed.

WP - JS - Get Instance of Tinymce Editor

I'm creating a Wordpress plugin, which adds a metabox right under the post editor containing a button. The plugin also loads a Javascript file right below the closing </body> tag.
PURPOSE
At the moment, what I am trying to achieve with the plugin is simple. When a user enters content to the editor and then clicks the button inside the metabox, I want to modify the editor's content.
JS CODE
In its simplest form:
jQuery(document).ready(function($) {
$('#button').on('click', function(e) {
e.preventDefault();
var editor = tinyMCE.get("content");
editor.setContent(some_content);
});
});
PROBLEM
The problem is that editor variable returns undefined.
FIREBUG (when trying to set var editor)
wpActiveEditor : "content"
editors : [ ]
activeEditor : null
WHAT HAVE I TRIED
I have tried many, many things (also many small tweaks) found on Tinymce's documentation and here on Stackoverflow but the problem still remains the same.
Any help would be very appreciated.
PS. The content textarea is visible when running my tests.
When the Editor first loads with the "Text" mode active, tinymce does not get initialized, therefore you cannot use tinyMCE.get(), as opposed to the "Visual" mode.
(I hadn't noticed that it actually works on the "Visual" mode, as I was keep testing it on the "Text" mode)
So, a conditional statement is necessary to determine first which tab is active. I solved my problem with this method:
function setEditorContent(val) {
var $_editorTextArea = $('#content');
$_editorTextArea.is(':visible') ? $_editorTextArea.val(val) : tinyMCE.get('content').setContent(val);
}
Hope this answer will prevent some headaches :)
Well, a live example would help a lot.
This way i can only guess: It looks a bit as if you cannot get the editor you want.
There are two possible reasons that come into my mind:
The editor id you are using is not the id of your editor
To verify this you check the id of your editors soure html element (in most cases a textarea).If there is no id set tinymce will use "content" as default.
There iy no editor initialized at all
To verify this you can use console.log(tinymce.editors) in your javascript console. If no editor is initialized then you will get an empty array.
Many years later but maybe this will help someone...
In addition to everything said above some consideration needs to be paid to the JS event model. Consider:
TinyMCE may not initialize (and the tinymce global may not be available) until the document is done loading. The OP correctly wrapped calls in jQuery(fn), which will solve this. This is relevant if you're using an added framework that initializes and tries to manipulate the editors (like AngularJS directives).
Parts of initialization seem to be asynchronous so even if you wrap everything in jQuery(fn) the editors may not be available until later. WP loads Underscore as part of Backbone so wrapping initial attempts to locate editors in _.defer(fn) seems to get me lots of mileage. This could be done with the native JS setTimeout as well.
Beyond the fantastic answer by #m.spyratos, it may be helpful to note that you can hook mode change events (Visual/Text) by adding a jQuery click event handler to button.switch-tmce[data-wp-editor="my_editor_id"] and button.switch-html[data-wp-editor="my_editor_id"] for when the user selects Visual or Text, respectively. Your version may vary but I found that the textarea goes away when switching to Visual mode and the tinymce.editor instance goes away when switching to Text mode. Hooking to these events gives a persistent means to re-hook when the user decides to change modes.
As a quick reference, you can attach to the editor object (activeEditor or something in editors[], which is keyed by editor ID) to receive any and all changes in visual editor content with by hooking to the editor with editor.on('NodeChange keyup', fn) and a single event callback. I included blur in my solution as well, for posterity. The text editor content can be hooked with jQuery('textarea#my_editor_id').on('keyup', fn).
I have successfully managed multiple editors on a page that are entirely two-way bound entirely through JS; the editors are created with wp_editor and no initial content then loaded asynchronously (via AJAX in my case) and managed through multiple edit cycles without a server round-trip. This is possible, if not slightly convoluted.

What is better in this case, document.createElement or document.write?

Ok, so I'm making an html5 canvas/javascript game. I'm playing around with the idea of making it available to anyone who wants to put the game on their own website, via one little script snippet that links to an external js file.
Inside the external js file, the whole entire game is included, all I need is to find the best way to create a canvas tag via javascript code.
The external js link:
<script src="http://host.com/game.js"></script>
Here is the single line of canvas code that I need to insert into the document:
<canvas id="canvas" style="display:block;margin:0px auto;" width="600" height="550">Your browser does not support the HTML5 canvas element.</canvas>
1. My first option would be to use..
document.write('<canvas id="canvas" style="display:block;margin:0px auto;" width="600" height="550">Your browser does not support the HTML5 canvas element.</canvas>');
However, document.write is frowned upon from what I understand.
2. My next option is to use..
document.createElement(canvas);
document.setAttribute(.....);
document.appendChild(....);
However, this option means I must include a div or some element with the external js link, so that I can append the canvas to it.
3. My last known option is to use..
document.getElementById('divWrapper').innerHTML('my canvas code');
However, this option also means I must include a div with the external js link, so that I can find the id of the div, and write inside it via innerHTML.
Last tip: People will be able to copy the external js link and paste it on their own website in the body, (it will not be in the head), and if my option requires a div tag with the script link, that is fine. I'm going for the least amount of characters that the person has to copy/paste.
So what option would you recommend? Is there another better way that I didn't mention?
I should probably make this an answer.
If document.write [docs] is called when the HTML is parsed (which seems to be the case), then it's perfectly fine to use it.
I would not write longer HTML code with it, but one line of HTML is ok.
Advantages of document.write: (in this case)
Easier for the user to add to his page (just copy and past).
Advantages of innerHTML:
You could provide the user the option to specify the id of the element to append the canvase to. This increases the flexibility for the user, but requires an additional step.
document.write is deprecated, don't use it.
I'd use innerHTML. Adding one div is totally fine and it gives the people, who insert the game, more control where to insert it.
document.write is not a good idea as it only works when called before the document is completely loaded.
A good idea is to use DOM as it is more x-browser.
var canvas = document.createElement('canvas');
canvas.setAttribute(...);
document.getElementById(...).appendChild(canvas);
PPK had run a test on innerhtml vs dom and here is his finding, http://www.quirksmode.org/dom/innerhtml.html, all votes/praises for innerHTML

How does one properly test a javascript widget?

So, I've written a little javascript widget. All a user has to do is paste a script tag into the page, and right below it I insert a div with all of the content the user has requested.
Many sites do similar things, such as Twitter, Delicious and even StackOverflow.
What I'm curious about is how to test this widget to make sure that it will work properly on everyone's webpage. I'm not using an iframe, so I really want to make sure that this code will work when inserted most places. I know it looks the same in all browsers.
Suggestions? Or should I just build one hundred web pages and insert my script tag and see if it works? I would hope there is an easier way than that.
Once you have confirmed that your javascript works cross-browser in a controlled environment, here are some things that might cause problems when used on an actual website:
CSS
You're using a CSS class that is already being used (for a different purpose) by the target website
You're using positioning that might interfere with the site's CSS
The elements you are using are being styled by the website's CSS (you might want to use some sort of "reset" CSS that applies only to your widget)
HTML
You're creating elements with the same id attribute as an element that already exists on the website
You're specifying a name attribute that is already being used (while name can be used for multiple elements, you may not be expecting that)
Javascript
What is the expected behaviour without Javascript enabled? If your script creates everything, is it acceptable for nothing to be present without JS?
At very basic you should make sure your widget works for following test-cases. I am sure then it will work on all web-pages -
http/https: There should not be any warning for HTTPS pages for unencrypted content.
<script> / <no-script>: What if JavaScript is disabled? Is your widget still visible?
What happens when third-party cookies are disabled? Does your widget still work?
Layout-box restrictions: When parent div element's size is less than your widget. Does your widget overflow the given size and destroys owners page?
By keeping all your Javascripts under a namespace (global object) with a very unique name, you should be pretty much OK. Also, you can simply use an anonymous function if you just want to print out something.
Similar question: How to avoid name clashes in JavaScript widgets

Categories

Resources