Hi I followed the instructions to create an extension.
My issue is that I can inject text on the fly but not HTML. Firefox block the character "<"
Here is my code in my XUL file.
<?xml version="1.0"?>
<overlay id="sample"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="jquery.js" />
<script>
var myExtension = {
init: function() {
// The event can be DOMContentLoaded, pageshow, pagehide, load or unload.
if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);
},
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered the event
var win = doc.defaultView; // win is the window for the doc
if (win != win.top) return; //only top window.
$("body",doc).html('WORK');
$("body",doc).html('<div>NOT WORKING</div>');
}
}
window.addEventListener("load", function() { myExtension.init(); }, false);
</script>
</overlay>
Thank you very much for your help
This is a XUL file, it has to use XML syntax. In particular, XML tags inside <script> elements will be interpreted as such - and you definitely don't want it. To prevent it you can wrap your script into a CDATA section:
<script>
<![CDATA[
doSomething("<foo>bar</foo>");
]]>
</script>
This makes sure that the tag contents are really interpreted as text.
Related
I have a webview in my page where I'm showing a chart(Fusion Chart).
I wrote a html page with js function as follows:
<html lang="en">
<head>
<script src="file:///android_asset/fusioncharts.js"></script>
<script src="file:///android_asset/fusioncharts.charts.js"></script>
</head>
<body>
<div id="chart-container"></div>
<script>
function loadChart(chartData) {
const dataSource = {
chart: {
theme: "fusion",
"showPlotBorder": "1",
"plotBorderColor": "#ffffff"
},
data: chartData
};
FusionCharts.ready(function () {
var myChart = new FusionCharts({
type: "column2d",
renderAt: "chart-container",
width: "100%",
height: "100%",
dataFormat: "json",
dataSource
}).render();
});
}
loadChart(chartData);
</script>
</body>
</html>
I need to pass data to the loadchart function from my shared project with the help of my webview. Is this possible?
There are so many ways of doing this on Android, though I would caution you to test it well on different devices depending on what default browser is being used for the WebView.
Luckily, since you are using Xamarin Forms, you could just use the Javascript Evaluation function that enables you to just put your JS code inside the function. And then time it right, and you can call a JS function which will take values from your C#.
Here's the documentation by MS on the functions
Eval() or EvaluateJavaScriptAsync().
Here are some examples of it's usage:
webView.EvaluateJavaScriptAsync(string.Format("document.getElementById(\"{0}\").value = \"{1}\"", "langs1", from));
webView.EvaluateJavaScriptAsync(string.Format("DDMENU(0)"));
Let me know if you have any questions!
I have an issue when using bootstrap 3 & prototype.js together on a magento website.
Basically if you click on the dropdown menu (Our Products) & then click on the background, the dropdown menu (Our Products) disappears (prototype.js adds "display: none;" to the li).
Here is a demo of the issue:
http://ridge.mydevelopmentserver.com/contact.html
You can see that the dropdown menu works like it should without including prototype.js on the page at the link below:
http://ridge.mydevelopmentserver.com/
Has anyone else ran into this issue before or have a possible solution for the conflict?
EASY FIX:
Just replace Magento's prototype.js file with this bootstrap friendly one:
https://raw.github.com/zikula/core/079df47e7c1f536a0d9eea2993ae19768e1f0554/src/javascript/ajax/original_uncompressed/prototype.js
You can see the changes made in the prototype.js file to fix the bootstrap issue here:
https://github.com/zikula/core/commit/079df47e7c1f536a0d9eea2993ae19768e1f0554
NOTE: JQuery must be include in your magento skin before prototype.js.. Example:
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/prototype/prototype.js"></script>
<script type="text/javascript" src="/js/lib/ccard.js"></script>
<script type="text/javascript" src="/js/prototype/validation.js"></script>
<script type="text/javascript" src="/js/scriptaculous/builder.js"></script>
<script type="text/javascript" src="/js/scriptaculous/effects.js"></script>
<script type="text/javascript" src="/js/scriptaculous/dragdrop.js"></script>
<script type="text/javascript" src="/js/scriptaculous/controls.js"></script>
<script type="text/javascript" src="/js/scriptaculous/slider.js"></script>
<script type="text/javascript" src="/js/varien/js.js"></script>
<script type="text/javascript" src="/js/varien/form.js"></script>
<script type="text/javascript" src="/js/varien/menu.js"></script>
<script type="text/javascript" src="/js/mage/translate.js"></script>
<script type="text/javascript" src="/js/mage/cookies.js"></script>
<script type="text/javascript" src="/js/mage/captcha.js"></script>
I've also used code from here: http://kk-medienreich.at/techblog/magento-bootstrap-integration-mit-prototype-framework but without a need to modify any source. Just put code below somewhere after prototype and jquery includes:
(function() {
var isBootstrapEvent = false;
if (window.jQuery) {
var all = jQuery('*');
jQuery.each(['hide.bs.dropdown',
'hide.bs.collapse',
'hide.bs.modal',
'hide.bs.tooltip',
'hide.bs.popover',
'hide.bs.tab'], function(index, eventName) {
all.on(eventName, function( event ) {
isBootstrapEvent = true;
});
});
}
var originalHide = Element.hide;
Element.addMethods({
hide: function(element) {
if(isBootstrapEvent) {
isBootstrapEvent = false;
return element;
}
return originalHide(element);
}
});
})();
Late to the party, but found this github issue which links to this informational page which links to this jsfiddle which works really nicely. It doesn't patch on every jQuery selector and is, I think, the nicest fix by far. Copying the code here to help future peoples:
jQuery.noConflict();
if (Prototype.BrowserFeatures.ElementExtensions) {
var pluginsToDisable = ['collapse', 'dropdown', 'modal', 'tooltip', 'popover'];
var disablePrototypeJS = function (method, pluginsToDisable) {
var handler = function (event) {
event.target[method] = undefined;
setTimeout(function () {
delete event.target[method];
}, 0);
};
pluginsToDisable.each(function (plugin) {
jQuery(window).on(method + '.bs.' + plugin, handler);
});
};
disablePrototypeJS('show', pluginsToDisable);
disablePrototypeJS('hide', pluginsToDisable);
}
Using the * selector with jQuery is not advised. This takes every DOM object on the page and puts it in the variable.
I would advice to select the elements that use a Bootstrap component specific. Solution below only uses the dropdown component:
(function() {
var isBootstrapEvent = false;
if (window.jQuery) {
var all = jQuery('.dropdown');
jQuery.each(['hide.bs.dropdown'], function(index, eventName) {
all.on(eventName, function( event ) {
isBootstrapEvent = true;
});
});
}
var originalHide = Element.hide;
Element.addMethods({
hide: function(element) {
if(isBootstrapEvent) {
isBootstrapEvent = false;
return element;
}
return originalHide(element);
}
});
})();
Very late to the party: if you don't feel like having extra scripts running, you can add a simple CSS override to prevent it from getting hidden.
.dropdown {
display: inherit !important;
}
Generally the use of !important in CSS is advised against, but I think this counts as an acceptable use in my opinion.
see http://kk-medienreich.at/techblog/magento-bootstrap-integration-mit-prototype-framework/.
It's quite an easy fix to validate the namespace of the element clicked.
Add a validation function to prototype.js:
and after that, validate the namespace before the element will be hidden:
hide: function(element) {
element = $(element);
if(!isBootstrapEvent)
{
element.style.display = 'none';
}
return element;
},
Replacing Magento's prototype.js file with the bootstrap friendly version suggested by MWD is throwing an error that prevents saving configurable products:
Uncaught TypeError: Object [object Array] has no method 'gsub' prototype.js:5826
(Running Magento Magento 1.7.0.2)
evgeny.myasishchev solution worked great.
(function() {
var isBootstrapEvent = false;
if (window.jQuery) {
var all = jQuery('*');
jQuery.each(['hide.bs.dropdown',
'hide.bs.collapse',
'hide.bs.modal',
'hide.bs.tooltip'], function(index, eventName) {
all.on(eventName, function( event ) {
isBootstrapEvent = true;
});
});
}
var originalHide = Element.hide;
Element.addMethods({
hide: function(element) {
if(isBootstrapEvent) {
isBootstrapEvent = false;
return element;
}
return originalHide(element);
}
});
})();
This answer helped me to get rid of bootstrap and prototype conflict issue.
As #GeekNum88 describe the matter,
PrototypeJS adds methods to the Element prototype so when jQuery tries
to trigger the hide() method on an element it is actually firing the
PrototypeJS hide() method, which is equivalent to the jQuery
hide() method and sets the style of the element to display:none;
As you suggest in the question itself either you can use bootstrap friendly prototype or else you can simply comment out few lines in bootstrap as bellow,
inside the Tooltip.prototype.hide function
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
I realise that this is a pretty old post by now, but an answer that no-one else seems to have mentioned is simply "modify jQuery". You just need a couple of extra checks in jQuery's trigger function which can be found around line 332.
Extend this if statement:
// Call a native DOM method on the target with the same name name as the event.
// Don't do default actions on window, that's where global variables be (#6170)
if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
... to say this:
// Call a native DOM method on the target with the same name name as the event.
// Don't do default actions on window, that's where global variables be (#6170)
// Check for global Element variable (PrototypeJS) and ensure we're not triggering one of its methods.
if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) &&
( !window.Element || !jQuery.isFunction( window.Element[ type ] ) ) ) {
"#6170" only seems to be mentioned in jQuery once so you can do a quick check for that string if you're working with a compiled (complete) jQuery library.
I am looking for a way to make the CKEDITOR wysiwyg content interactive. This means for example adding some onclick events to the specific elements. I can do something like this:
CKEDITOR.instances['editor1'].document.getById('someid').setAttribute('onclick','alert("blabla")');
After processing this action it works nice. But consequently if I change the mode to source-mode and then return to wysiwyg-mode, the javascript won't run. The onclick action is still visible in the source-mode, but is not rendered inside the textarea element.
However, it is interesting, that this works fine everytime:
CKEDITOR.instances['editor1'].document.getById('id1').setAttribute('style','cursor: pointer;');
And it is also not rendered inside the textarea element! How is it possible? What is the best way to work with onclick and onmouse events of CKEDITOR content elements?
I tried manually write this by the source-mode:
<html>
<head>
<title></title>
</head>
<body>
<p>
This is some <strong id="id1" onclick="alert('blabla');" style="cursor: pointer;">sample text</strong>. You are using CKEditor.</p>
</body>
</html>
And the Javascript (onclick action) does not work. Any ideas?
Thanks a lot!
My final solution:
editor.on('contentDom', function() {
var elements = editor.document.getElementsByTag('span');
for (var i = 0, c = elements.count(); i < c; i++) {
var e = new CKEDITOR.dom.element(elements.$.item(i));
if (hasSemanticAttribute(e)) {
// leve tlacitko mysi - obsluha
e.on('click', function() {
if (this.getAttribute('class') === marked) {
if (editor.document.$.getElementsByClassName(marked_unique).length > 0) {
this.removeAttribute('class');
} else {
this.setAttribute('class', marked_unique);
}
} else if (this.getAttribute('class') === marked_unique) {
this.removeAttribute('class');
} else {
this.setAttribute('class', marked);
}
});
}
}
});
Filtering (only CKEditor >=4.1)
This attribute is removed because CKEditor does not allow it. This filtering system is called Advanced Content Filter and you can read about it here:
http://ckeditor.com/blog/Upgrading-to-CKEditor-4.1
http://ckeditor.com/blog/CKEditor-4.1-Released
Advanced Content Filter guide
In short - you need to configure editor to allow onclick attributes on some elements. For example:
CKEDITOR.replace( 'editor1', {
extraAllowedContent: 'strong[onclick]'
} );
Read more here: config.extraAllowedContent.
on* attributes inside CKEditor
CKEditor encodes on* attributes when loading content so they are not breaking editing features. For example, onmouseout becomes data-cke-pa-onmouseout inside editor and then, when getting data from editor, this attributes is decoded.
There's no configuration option for this, because it wouldn't make sense.
Note: As you're setting attribute for element inside editor's editable element, you should set it to the protected format:
element.setAttribute( 'data-cke-pa-onclick', 'alert("blabla")' );
Clickable elements in CKEditor
If you want to observe click events in editor, then this is the correct solution:
editor.on( 'contentDom', function() {
var element = editor.document.getById( 'foo' );
editor.editable().attachListener( element, 'click', function( evt ) {
// ...
// Get the event target (needed for events delegation).
evt.data.getTarget();
} );
} );
Check the documentation for editor#contentDom event which is very important in such cases.
I am writing a Firefox extension using JavaScript and XUL. Part of my code needs to be able to take some XUL markup and dynamically append it inside an existing container element. So basically I need to appendChild() but with a text string instead of a Node object. To do this, I tried the method listed in this question. Unfortunately this does not seem to work. It appears that div.childNodes returns an empty nodeList, which I can't even append to the container. The error is
Error: Could not convert JavaScript argument arg 0 [nsIDOMXULElement.appendChild]
I'm not quite sure what I am doing wrong. Is there a way to make this work, or some alternate method to dynamically set the container's markup?
Note: The container element is of type richlistbox.
function updateContainerData(containerName){
try{
var resultsArray = DB.queryAsync("SELECT nodeData FROM waffleapps_privateurl");
container = document.getElementById(containerName);
for (var i = 0; i < resultsArray.length; i++) {
/*
// This works - appending an actual Node ( duplicate from a template)
template = document.getElementById("list-item-template");
dupNode = template.cloneNode(true);
dupNode.setAttribute("hidden", false);
container.appendChild(dupNode);
*/
// This doesn't work
div = document.createElement("div");
//var s = '<li>text</li>';
var s = "<richlistitem id ='list-item-template'><hbox><checkbox label='' checked='true'/> <description>DESCRIPTION</description><textbox>test</textbox><textbox></textbox></hbox></richlistitem>";
div.innerHTML = s;
var elements = div.childNodes;
container.appendChild(elements); // error
}
}
catch(err){
alert( "Error: " + err.message);
}
}
I have gotten a bit further by using the following code. Now I am able to insert HTML elements in the container, but it appears that XUL elements are not parsed properly - the checkbox and textbox do not appear. I'm not sure how I would change this so it parses the HTML and XUL markup correctly.
var s = "<richlistitem id ='list-item-template'><hbox><checkbox label='' checked='true'/> <description>DESCRIPTION</description><textbox>test</textbox><textbox></textbox></hbox></richlistitem>";
var dp = new DOMParser();
container.appendChild(dp.parseFromString(s, "text/xml").documentElement);
You need to do an appendChild for each element in the "elements" nodeList (assuming there's more than one).
Also note: a list element should have a parent ol or ul element.
I finally figured out how to properly parse and append a XUL markup string. I was able to use the parseFromString method from a new DOMParser(). I had to make sure that the element's markup specified the namespace (xmlns) so the parser knew it was XUL markup.
The code below shows a full example.
test.js:
test = function(){
alert("testing");
container = document.getElementById("testing");
var dp = new DOMParser();
// must specify namespace
var s = "<textbox xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' value='test' size='20'></textbox>";
element = dp.parseFromString(s, "text/xml").documentElement;
container.appendChild(element);
document.getElementById("testing");
}
test.xul:
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin/" ?>
<?xml-stylesheet type="text/css"
href="chrome://testextensionname/skin/test.css" ?>
<!DOCTYPE window SYSTEM
"chrome://testextensionname/locale/test.dtd">
<window xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="testWindow"
orient="vertical" title="TEST" statictitle="TEST"
width="50" height="50;" screenX="10" screenY="10"
>
<script type="application/x-javascript" src="chrome://testextensionname/content/test.js" />
<hbox id="testing">
<button label="Go" oncommand="test()"/>
<textbox value='test' size='20'></textbox>
</hbox>
</window>
I'm attempting to load the excanvas polyfill in the page-specific js file for my page. This script file is inserted after the body tag on my page.
The odd bit is that if I use
<script type='text/javascript' src='/Scripts/polyfills/excanvas.compiled.js'></script>
in my head tag, everything works great, but I don't necessarily want to load this script for HTML5 compliant browsers if I don't have to.
So naturally I tried to use Modernizr to load it selectively. This is my perfectly executing, but non-functioning javascript code:
<!-- language: lang-js -->
$(function () {
Modernizr.load({
test: Modernizr.canvas,
nope: '/Scripts/polyfills/excanvas.compiled.js',
complete: function () {
setImage();
}
});
});
This seems to work fine. The excanvas script appears to load successfully.
The setImage function creates the canvas element dynamically and adds it to a div on the page.
This works fine in IE9 but fails to render in IE8.
<!-- language: lang-js -->
function setImage() {
var canvasHello = document.createElement('canvas');
canvasHello.id = 'canvasHello';
$('#divContent').append(canvasHello);
if (!Modernizr.canvas) {
G_vmlCanvasManager.initElement(canvasHello);
}
var canvasContext = canvasHello.getContext('2d');
canvasContext.width = 800;
canvasContext.height = 600;
canvasContext.fillStyle = "#000000";
canvasContext.fillRect(0, 0, 600, 800);
var img = document.createElement('img');
img.src = '/Content/images/hello.png';
img.onload = function () {
canvasContext.drawImage(img, 100, 25, 100, 100);
}
}
Did I miss something or does the excanvas script not function outside of the head tag?
in the given requirement you could use the IE conditional statements like this...
<!--[if lt IE 9]>
<script src="script/excanvas.js"></script>
<![endif]-->
would suffice....
the statement will only be understood by IE version less than 9 and the script tag gets attached.
The only thing you missed is the instructions on how to use excanvas:
The excanvas.js file must be included in the page before any occurrences of canvas elements in the markup. This is due to limitations in IE and we need to do our magic before IE sees any instance of in the markup. It is recommended to put it in the head.