How to place a custom control inside the map div in ol3? - javascript

I'm sorry, this question is irrelevant to ol3 and there were some evident code errors (Note from the author)
I'm rewriting a Ol 2 map application with the most recent version of Openlayers 3.15.1. I need to add custom controls to manipulate sea surface temperature maps. I want to place the custom controls over the map . However after trying to recreate the code of some examples showing how to write custom controls with Ol3, I have found some drawbacks to correctly recreate it.
The custom control is composed by a small icon and clicking over it does some stutf. Here below I show several versions of the code used. Basically the controls are created by a function that loads initially.
Only one of them works properly and I would like to understand why the others do not. All examples are almost equivalent two are with pure javascript and two with JQuery trying to look for a optimal solution.
Code 1: Pure Javascript but using innerHTML to insert the image into a . The image seems to be not inserted into the DOM.
var texto = "<img id=\"tool_draw\" src=\"/js/Saidin/Image/draw_line_off.png\">";
var element = document.createElement('div');
element.innerHTML=texto;
element.className = 'ol-unselectable ol-mycontrol';
element.style.position="absolute";
element.style.width="24px";
element.style.top= "70px";
element.style.left= "9px";;
var action= function(e){ alert('hola'); }
document.getElementById("tool_draw").addEventListener("click", action, false);
var okk= new ol.control.Control({
element:element
});
map.addControl(okk);
This code does not work. The error is: document.getElementById(...) is null
Code 2: Pure Javascript but creating the image with the constructor and that's all!
var texto = "/js/Saidin/Image/draw_line_off.png";
var boton = document.createElement('img');
boton.src=texto;
boton.className = 'ol-unselectable ol-mycontrol';
boton.setAttribute("id","tool_draw");
boton.style.position="absolute";
boton.style.top= "70px";
boton.style.left= "9px";
var action= function(e){ alert('hola'); }
boton.addEventListener("click", action, false);
var okk= new ol.control.Control({
element:boton
});
map.addControl(okk);
This code works fine !
Code 3: I think is Equivalent to Code 1 but using JQuery library
var texto ="<img id=\"tool_draw\" src=\"/js/Saidin/Image/draw_line_off.png\">";
$('body').append($('<div/>', {
id:'hola',
'class' : 'ol-unselectable ol-mycontrol',
texto:texto,
css: { "position":"absolute","top": "70px", "left":"9px" }
}));
element=$('#hola');
var cont= function(e){ alert('hola'); }
$("#tool_draw").on('click', cont );
var okk= new ol.control.Control({
element:element
});
map.addControl(okk);
This code does not work. The error is: TypeError: Argument 1 of Node.appendChild does not implement interface Node..
Code 4: I think is equivalent to Code 2 but using JQuery library
var element=$('<img>', {
id:'tool_draw',
src:'/js/Saidin/Image/draw_line_off.png',
'class' : 'ol-unselectable ol-mycontrol',
css: { "position":"absolute","top": "70px", "left":"9px" }
});
$('#map').append(element);
var cont= function(e){ alert('hola'); }
element.on('click', cont );
var okk= new ol.control.Control({
element:element
});
map.addControl(okk);
This code works fine ! but... the same error from ol.js appear TypeError: Argument 1 of Node.appendChild does not implement interface Node.
Can somebody explain me what's wrong with the failing codes ?. I apologize for this long question and I'm not sure if the problem comes from JQuery, JavaScript or is related with the new OL3 version. Any explanation is welcome !. Thanks

code1 doesnt work cause you use getElementById while the element is not ready on dom. You may use element.addEventListener("click", action, false); but I am not sure if it would work.
Code 2 works cause you attach the listener directly to the element (like the way I suggest on 1) and you are not searching for it in the DOM (getElementById)
Code 3 doesnt work cause appendChild is a native DOM method and only accepts DOM nodes as a parameter. The element you're trying to append ($('body').append($('<div/>'.....) is a jQuery object, not a DOM element.
Code 4 shouldnt work for the same reason as 3.
Your problems have nothing to do with ol3. It is jquery & js problems. Hope I helped you a bit

Related

Proper Way Of Modifying Toolbar After Init in TinyMCE

I am extending a cloud-hosted LMS with javascript. Therefore, we can add javascript to the page, but cannot modify the vendor javascript for different components.
The LMS uses tinyMCE frequently. The goal is to add a new button on to the toolbar of each tinyMCE editor.
The problem is that since the tinyMCE modules are initialized in the vendor's untouchable code, we cannot modify the init() call. Therefore, we cannot add any text on to the "toolbar" property of the init() object.
So I accomplished this in a moderately hacky way:
tinyMCE.on('AddEditor', function(e){
e.editor.on('init', function(){
tinyMCE.ui.Factory.create({
type: 'button',
icon: 'icon'
}).on('click', function(){
// button pressing logic
})
.renderTo($(e.editor.editorContainer).find('.mce-container-body .mce-toolbar:last .mce-btn-group > div')[0])
});
});
So this works, but needless to say I am not totally comfortable having to look for such a specific location in the DOM like that to insert the button. Although this works, I do not believe it was the creator's intention for it to be used like this.
Is there a proper way to add the button to a toolbar, after initialization, if we cannot modify the initialization code?
I found a more elegant solution, but it still feels a bit like a hack. Here is what I got:
// get an instance of the editor
var editor=tinymce.activeEditor; //or tinymce.editors[0], or loop, whatever
//add a button to the editor buttons
editor.addButton('mysecondbutton', {
text: 'My second button',
icon: false,
onclick: function () {
editor.insertContent(' <b>It\'s my second button!</b> ');
}
});
//the button now becomes
var button=editor.buttons['mysecondbutton'];
//find the buttongroup in the toolbar found in the panel of the theme
var bg=editor.theme.panel.find('toolbar buttongroup')[0];
//without this, the buttons look weird after that
bg._lastRepaintRect=bg._layoutRect;
//append the button to the group
bg.append(button);
I feel like there should be something better than this, but I didn't find it.
Other notes:
the ugly _lastRepaintRect is needed because of the repaint
method, which makes the buttons look ugly regardless if you add new
controls or not
looked in the code, there is no way of adding new controls to the
toolbar without repainting and there is no way to get around it
without the ugly hack
append(b) is equivalent to add(b).renderNew()
you can use the following code to add the button without the hack, but you are shortcircuiting a lot of other stuff:
Code:
bg.add(button);
var buttonElement=bg.items().filter(function(i) { return i.settings.text==button.text; })[0];
var bgElement=bg.getEl('body');
buttonElement.renderTo(bgElement);

Polymer Selenium Test Accessing Sub-Element Data

In a firebase-login element I have
<paper-button id="btnLogin" data-dialog="login-modal" on-tap="toggleLogin">
<iron-icon icon="account-box"></iron-icon>
Login
</paper-button>
Where toggleLogin calls:
toggleLogin: function() {this.$.loginModal.toggle();},
In the Polymer test suite I am using:
Polymer.dom(element.root).querySelector('#btnLogin').click();
But Selenium is giving me the error of:
this.$.loginModal.toggle is not a function
Long story short, how can I click the button and check the modal pops up?
Note: Polymer team's test looks like:
Polymer.dom(myEl.root).querySelector('button').click()
Since they are naming their element myEl instead of element and looking for the button tag instead of the tag with id of btnLogin I felt that my solution was suitable. What am I doing wrong here?
UPDATE:
While looking at the bind event I still have not gotten things working.
CODE:
var btnLogin = Polymer.dom(myEl.root).querySelector('#btnLogin');
// This does the same thing as
// var btnLogin = element.$.btnLogin;
btnLogin.click.bind(btnLogin);
The above code allows me to move past the line but does not actually toggle the dialog. I am not sure why. When I add in click() instead of click it gives me the this.$.loginModal.toggle() is not defined error that I have been struggling with.
UPDATE:
Still have not found a good answer to this. Was looking into some code that may help and found the submenu element that wants to know information about it's content elements. I will include their testing below.
CODE:
suite('<paper-submenu>', function() {
var menu,
sub1, sub2, sub3,
collapse1, collapse2, collapse3,
trigger1, trigger2, trigger3;
setup(function() {
menu = fixture('basic');
sub1 = menu.querySelectorAll('paper-submenu')[0];
sub2 = menu.querySelectorAll('paper-submenu')[1];
sub3 = menu.querySelectorAll('paper-submenu')[2];
collapse1 = Polymer.dom(sub1.root).querySelector('iron-collapse');
collapse2 = Polymer.dom(sub2.root).querySelector('iron-collapse');
collapse3 = Polymer.dom(sub3.root).querySelector('iron-collapse');
trigger1 = sub1.querySelector('.menu-trigger');
trigger2 = sub2.querySelector('.menu-trigger');
trigger3 = sub3.querySelector('.menu-trigger');
});
test('selecting an item expands the submenu', function() {
assert.isFalse(collapse1.opened);
assert.isFalse(collapse2.opened);
assert.isFalse(collapse3.opened);
MockInteractions.tap(trigger1);
assert.isTrue(collapse1.opened);
assert.isFalse(collapse2.opened);
assert.isFalse(collapse3.opened);
});
Following the above example I tried the following:
test('Login Modal Opens', function(done) {
expect(loginModal).to.exist;
console.log(loginModal);
console.dir(loginModal);
expect(loginModal.opened).to.exist;
assert.isFalse(loginModal.opened);
btnLogin.click.bind(btnLogin);
assert.isTrue(loginModal.opened);
});
Unfortunately I am getting loginModal.opened as undefined. loginModal.toggle() gives toggle is not a function error.
UPDATE:
I found that bind does not actually call the function. It only binds the this to a new location. So when I was doing btnLogin.click.bind(btnLogin) it was doing the binding so when I called btnLogin.click() it would have a binding to btnLogin rather than ... btnLogin. Therefore it would have been the same to just call btnLogin.click() without ever calling the bind function.
Now that this is figured out, I decided to mess with call instead of bind but again I only was binding the this to the same scope so that was no help. I then tried btnLogin.click.call(element) but it still gave me the error that this.$.loginModal.toggle is not a function.
Just a wild guess, I don't know JS well
var el = Polymer.dom(element.root).querySelector('#btnLogin');
el.click().bind(el)();

addEventListener to div element

I am trying to fire a script when the contents of a div are altered, specifically when a div receives the next set of results from a js loaded paginator.
I have this:
<script script type="text/javascript" language="javascript">
document.addEventListener("DOMCharacterDataModified", ssdOnloadEvents, false);
function ssdOnloadEvents (evt) {
var jsInitChecktimer = setInterval (checkForJS_Finish, 111);
function checkForJS_Finish () {
if ( document.querySelector ("#tester")
) {
clearInterval (jsInitChecktimer);
//do the actual work
var reqs = document.getElementById('requests');
var reqVal = reqs.get('value');
var buttons = $$('.clicker');
Array.each(buttons, function(va, index){
alert(va.get('value'));
});
}
}
}
</script>
This works well when the doc loads (as the results take a few seconds to arrive) but I need to narrow this down to the actual div contents, so other changes on the page do not fire the events.
I have tried:
var textNode = document.getElementById("sitepage_content_content");
textNode.addEventListener("DOMCharacterDataModified", function(evt) {
alert("Text changed");
}, false);
But the above does not return anything.
Can what I am trying to do be done in this way? If yes where am I going wrong?
Using Social Engine (Zend) framework with MooTools.
I did this in the end with a little cheat :-(
There is a google map loading on the page that sets markers to match the location of the results. So I added my events to the end this code namely: function setMarker() {}.
I will not mark this as the correct answer as it is not really an answer to my question, but rather a solution to my problem, which is localised to the Social engine framework.
I will add a Social engine tag to my original question in the hope it may help someone else in the future.
Thanks guys.

using onmouseover to change text hyperlink into an image hyperlink?

Please bear with me I am brand new to learning javascript (self taught)! I am usually one to find answers on my own from just web browsing but so far I haven't found any resources explaining how to accomplish the following:
So, basically all I want to do is change this (HTML):
SPEAKERS
to an image by using javascript.
The image is kept in the same folder as the html and the js.
Here is as far as I know to go with the javascript:
function showImage()
{
picture = new Image(100,100);
picture.src = "icon2.png";
document.getElementById("speakers").innerHTML = picture.src;
}
function goBack()
{
document.getElementById("speakers").innerHTML="SPEAKERS";
}
For clarity, all I would like to do is change the text ("SPEAKERS") to an image using 'onmouseover' while using the same hyperlink in the process.
It seems like a very simple problem but I don't know enough to determine if what I want to do is even possible. If it's not possible that's fine, I would just like to know either way ;P. Thanks ahead of time!
If you're ok with using jquery, you could use .html() and .hover()
http://jsfiddle.net/u8fsU/
Try something like this to get you started (not a complete nor tested solution):
var showImage = function(){
var picture = document.createElement("img");
picture.src = "icon2.png";
picture.href = "link.html";
var speakers = document.getElementById("speakers");
speakers.parentNode.replaceChild(speakers, picture);
}
Please see https://developer.mozilla.org/en-US/docs/Gecko_DOM_Reference for a good reference to some of the available DOM properties and methods.

Dynamic source attribute update not working in chromium

I have a script of which the part relevant to the question is:
<script type="text/javascript">
function imageOnClick() {
var image = $("#image_id");
$(image).attr("src", "ajax-loader.gif");
$.ajax({
// do staffs
complete: function () {
$(image).attr("src", "default.gif"); // ***
}
});
}
</script>
Everything works fine in Firefox and IE-8. However, in GoogleChrom(21.0.1180.83) the loading image is shown and then the complete is invoked, the source of image is changed, but not displayed. I have checked the image element's src attribute is changed to default.gif as expected but space of image is left blank.
Is this a common problem with a trivial solution? Or I have to rechech the large imageOnClick function?
This fiddle works for me in Chrome 21.0.1180.79.
I'm not sure why you are experiencing problems, but the extra selection of the image object is at least superfluous. var image = $("#image_id"); gives a jQuery object (or an array of them). Doing $(image) later will give you the exact same object.
And you might also want to read up on prop() vs. attr().

Categories