Overlapping Marker Spiderfier + MarkerWithLabel - google-maps-markers

Using the Google Maps JavaScript API v3 with Overlapping Marker Spiderfier and MarkerWithLabel has an adverse effect when spiderfying: all markers will spiderfy and then immediately return to their original position (not via unspiderfy) except for the first marker.
That is, the Marker event position_changed is triggered an additional n - 1 times after spiderfying, where n is the number of markers spiderfied.

The issue stems from the optimized Marker attribute, which MarkerWithLabel forces to false. Leaving optimized as true (the default setting) should result in correct spiderfying. Doing so requires a patch to the MarkerWithLabel source though: removing the lines that set optimized = false:
function MarkerWithLabel(opt_options) {
opt_options = opt_options || {};
opt_options.labelContent = opt_options.labelContent || "";
opt_options.labelAnchor = opt_options.labelAnchor || new google.maps.Point(0, 0);
opt_options.labelClass = opt_options.labelClass || "markerLabels";
opt_options.labelStyle = opt_options.labelStyle || {};
opt_options.labelInBackground = opt_options.labelInBackground || false;
if (typeof opt_options.labelVisible === "undefined") {
opt_options.labelVisible = true;
}
if (typeof opt_options.raiseOnDrag === "undefined") {
opt_options.raiseOnDrag = true;
}
if (typeof opt_options.clickable === "undefined") {
opt_options.clickable = true;
}
if (typeof opt_options.draggable === "undefined") {
opt_options.draggable = false;
}
// if (typeof opt_options.optimized === "undefined") {
// opt_options.optimized = false;
// }
opt_options.crossImage = opt_options.crossImage || "http" + (document.location.protocol === "https:" ? "s" : "") + "://maps.gstatic.com/intl/en_us/mapfiles/drag_cross_67_16.png";
opt_options.handCursor = opt_options.handCursor || "http" + (document.location.protocol === "https:" ? "s" : "") + "://maps.gstatic.com/intl/en_us/mapfiles/closedhand_8_8.cur";
// opt_options.optimized = false; // Optimized rendering is not supported
this.label = new MarkerLabel_(this, opt_options.crossImage, opt_options.handCursor); // Bind the label to the marker
// Call the parent constructor. It calls Marker.setValues to initialize, so all
// the new parameters are conveniently saved and can be accessed with get/set.
// Marker.set triggers a property changed event (called "propertyname_changed")
// that the marker label listens for in order to react to state changes.
google.maps.Marker.apply(this, arguments);
}

Related

html/css-/js drag and drop for mouse and touch combine with rotate with every click?

I use a script for moving an object both with mouse and touch screen. This works.
I have another script to make the object rotate 90 degrees with each click, this also works.
It just doesn't work together.
When I merge them, the move still works, but with a click the object moves back to the starting position and only rotates there.
I've read that I should merge this but I don't know how. Below both scripts.
Thanks in advance for responses.
var container = document.querySelector("#container");
var activeItem = null;
var active = false;
container.addEventListener("touchstart", dragStart, false);
container.addEventListener("touchend", dragEnd, false);
container.addEventListener("touchmove", drag, false);
container.addEventListener("mousedown", dragStart, false);
container.addEventListener("mouseup", dragEnd, false);
container.addEventListener("mousemove", drag, false);
function dragStart(e) {
if (e.target !== e.currentTarget) {
active = true;
// this is the item we are interacting with
activeItem = e.target;
if (activeItem !== null) {
if (!activeItem.xOffset) {
activeItem.xOffset = 0;
}
if (!activeItem.yOffset) {
activeItem.yOffset = 0;
}
if (e.type === "touchstart") {
activeItem.initialX = e.touches[0].clientX - activeItem.xOffset;
activeItem.initialY = e.touches[0].clientY - activeItem.yOffset;
} else {
console.log("doing something!");
activeItem.initialX = e.clientX - activeItem.xOffset;
activeItem.initialY = e.clientY - activeItem.yOffset;
}
}
}
}
function dragEnd(e) {
if (activeItem !== null) {
activeItem.initialX = activeItem.currentX;
activeItem.initialY = activeItem.currentY;
}
active = false;
activeItem = null;
}
function drag(e) {
if (active) {
if (e.type === "touchmove") {
e.preventDefault();
activeItem.currentX = e.touches[0].clientX - activeItem.initialX;
activeItem.currentY = e.touches[0].clientY - activeItem.initialY;
} else {
activeItem.currentX = e.clientX - activeItem.initialX;
activeItem.currentY = e.clientY - activeItem.initialY;
}
activeItem.xOffset = activeItem.currentX;
activeItem.yOffset = activeItem.currentY;
setTranslate(activeItem.currentX, activeItem.currentY, activeItem);
}
}
function setTranslate(xPos, yPos, el) {
el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
}
// Make blocks rotate 90 deg on each click
var count=0;
function rot(e){
count++;
var deg=count*90;
e.style.transform = "rotate("+deg+"deg)";
}
So I put them in a file but then it only works as described above.

In Boomla, how can I easily find the next sibling of a file

I'm quite used to nextSiblingand nextElementSibling in the DOM. Is there an easy way of doing a similar thing with Boomla files?
I would need the next sibling within the same placeholder (and null if this is the last), but I'd be interested about finding the next sibling in any placeholder (and null if this is the last file in the last placeholder).
Currently, there is no built-in method for this.
Here are 2 methods for the sjs-4 engine for getting the next in the placeholder or parent:
var nextInBucket = function(f) {
var bucket = f.bucketId();
var bucketSiblings = f.query("../:" + bucket);
var path = f.path();
var index = 0;
var found = false;
bucketSiblings.each(function(t) {
if (t.path() == path) {
found = true;
return false;
}
index++;
});
if ( ! found) {
return null;
}
return bucketSiblings.eq(index + 1);
}
var nextInParent = function(f) {
var parentChildren = f.query("../*");
var path = f.path();
var index = 0;
var found = false;
parentChildren.each(function(t) {
if (t.path() == path) {
found = true;
return false;
}
index++;
});
if ( ! found) {
return null;
}
return parentChildren.eq(index + 1);
}

Ace Editor: Lock or Readonly Code Segment

Using the Ace Code Editor can I lock or make readonly a segment of code but still allow other lines of code to be written or edited during a session?
Here is the start of a solution:
$(function() {
var editor = ace.edit("editor1")
, session = editor.getSession()
, Range = require("ace/range").Range
, range = new Range(1, 4, 1, 10)
, markerId = session.addMarker(range, "readonly-highlight");
session.setMode("ace/mode/javascript");
editor.keyBinding.addKeyboardHandler({
handleKeyboard : function(data, hash, keyString, keyCode, event) {
if (hash === -1 || (keyCode <= 40 && keyCode >= 37)) return false;
if (intersects(range)) {
return {command:"null", passEvent:false};
}
}
});
before(editor, 'onPaste', preventReadonly);
before(editor, 'onCut', preventReadonly);
range.start = session.doc.createAnchor(range.start);
range.end = session.doc.createAnchor(range.end);
range.end.$insertRight = true;
function before(obj, method, wrapper) {
var orig = obj[method];
obj[method] = function() {
var args = Array.prototype.slice.call(arguments);
return wrapper.call(this, function(){
return orig.apply(obj, args);
}, args);
}
return obj[method];
}
function intersects(range) {
return editor.getSelectionRange().intersects(range);
}
function preventReadonly(next, args) {
if (intersects(range)) return;
next();
}
});
see it working in this fiddle: http://jsfiddle.net/bzwheeler/btsxgena/
The major working pieces are:
create start and end ace anchors which track the location of a 'readonly' portion as the document around it changes.
create a range to encapsulate the anchors
add a custom keyhandler to check if the current impending keypress will affect the readonly range and cancel it if so.
add custom paste/cut handlers to protect against right-click menu and browser menu cut/paste actions
You can do it by listening to the exec events:
// Prevent editing first and last line of editor
editor.commands.on("exec", function(e) {
var rowCol = editor.selection.getCursor();
if ((rowCol.row === 0) || ((rowCol.row + 1) === editor.session.getLength())) {
e.preventDefault();
e.stopPropagation();
}
});
Source: https://jsfiddle.net/tripflex/y0huvc1b/
I suggest something else easier and more reliable to prevent range to be modified (check it!)
var old$tryReplace = editor.$tryReplace;
editor.$tryReplace = function(range, replacement) {
return intersects(range)?null:old$tryReplace.apply(this, arguments);
}
var session = editor.getSession();
var oldInsert = session.insert;
session.insert = function(position, text) {
return oldInsert.apply(this, [position, outsideRange(position)?text:""]);
}
var oldRemove = session.remove;
session.remove = function(range) {
return intersects(range)?false:oldRemove.apply(this, arguments);
}
var oldMoveText = session.moveText;
session.moveText = function(fromRange, toPosition, copy) {
if (intersects(fromRange) || !outsideRange(toPosition)) return fromRange;
return oldMoveText.apply(this, arguments)
}
outsideRange = function (position) {
var s0 = range.start;
if (position.row < s0.row || (position.row == s0.row && position.column <= s0.column)) return true; // position must be before range.start
var e0 = range.end;
if (position.row > e0.row || (position.row == e0.row && position.column >= e0.column)) return true; // or after range.end
return false;
}
intersects = function(withRange) {
var e = withRange.end, s0 = range.start, s = withRange.start, e0 = range.end;
if (e.row < s0.row || (e.row == s0.row && e.column <= s0.column)) return false; // withRange.end must be before range.start
if (s.row > e0.row || (s.row == e0.row && s.column >= e0.column)) return false; // or withRange.start must be after range.end
return true;
}

NicEdit link creation doesn't work in IE 8 and FireFox if text wasn't selected

I have a problem with nicEdit link creation tool in IE and Firefox.
In general, I think the problem is related to the execCommand in IE and FireFox. It seems document doesn't get updated after execCommand executes.
This is an example of my problem with nicEdit create link command.
if(!this.ln) {
var tmp = 'javascript:nicTemp();';
this.ne.nicCommand("createlink",tmp);
this.ln = this.findElm('A','href',tmp);
// set the link text to the title or the url if there is no text selected
alert(this.ln);
if (this.ln.innerHTML == tmp) {
this.ln.innerHTML = this.inputs['title'].value || url;
};
}
The code above is called when no text is selected, Chrome returns 'javascript:nicTemp()' for the alert(this.ln), while IE 8 and Firefox return 'undefined', so the next line after the alert encounters an error in IE and Firefox.
it seems findElem can't find the newly created link by nicCommand which in turn calls execCommand
I had similar problems when I try to find and modify tags created with execCommand, it seems the dom isn't updated to include them.
Am I right? How can I solve this problem? how can I force the document to be updated ....
please help
my trick for nicEdit, in the situation when no text is selected, is to paste the title given via the Add Link form into the document and select it, then the rest code works as it works when a text is selected.
I used the function pasteHtmlAtCaret described in the following link to paste the title
Insert html at caret in a contenteditable div
this.removePane();
var url = this.inputs.href.value;
var selected = getSelected();
var B= 'javascript:nicTemp()';
if (selected == '')
{
var B = url;
pasteHtmlAtCaret(this.inputs['title'].value || url,true);
}
if(!this.ln){
this.inputs.title.value;this.ne.nicCommand("createlink",B);
this.ln=this.findElm("A","href",B)
}
the getSelected is also a simple function as below
function getSelected()
{
if (document.selection)
return document.selection.createRange().text;
else
return window.getSelection();
}
Ahmad, just use this variation of the "submit" function to avoid the "insert/edit" problem with the link, it worked for me:
submit : function(e) {
var url = this.inputs['href'].value;
if(url == "http://" || url == "") {
alert("Introduce una URL valida para crear el Link.");
return false;
}
this.removePane();
if(!this.ln) {
//**************** YOUR CHANGE WITH A BIT OF VARIATION **************
var selected = this.getSelected();
var tmp = 'javascript:void(0)';
if (selected == '') {
tmp = url;
this.pasteHtmlAtCaret(this.inputs['title'].value || tmp, true);
}
//**************** END OF YOUR CHANGE WITH A BIT OF VARIATION **************
this.ne.nicCommand("createlink",tmp);
this.ln = this.findElm('A','href',tmp);
// set the link text to the title or the url if there is no text selected
if (this.ln.innerHTML == tmp) {
this.ln.innerHTML = this.inputs['title'].value || url;
};
}
if(this.ln) {
var oldTitle = this.ln.title;
this.ln.setAttributes({
href: this.inputs['href'].value,
title: this.inputs['title'].value,
target: '_blank'
});
// set the link text to the title or the url if the old text was the old title
if (this.ln.innerHTML == oldTitle) {
this.ln.innerHTML = this.inputs['title'].value || this.inputs['href'].value;
};
}
}
this.removePane();
var url = this.inputs['href'].value;
var selected = getSelected();
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
var tmp = "";
if(isChrome == true){
tmp=url;
}
else{tmp='javascript:nicTemp()'}
if (selected == '' && isChrome == false)
{
pasteHtmlAtCaret(this.inputs['title'].value || url,true);
}
if (!this.ln) {
//var tmp = this.inputs['title'].value == "" ? this.inputs['href'].value : this.inputs['title'].value;
this.ne.nicCommand("createlink", tmp);
this.ln = this.findElm('A', 'href', tmp);
}
function getSelected()
{
if (document.selection)
return document.selection.createRange().text;
else
return window.getSelection();
}
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
//create a link format
el.innerHTML = ''+ html +'';
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}

Get action when press two keys at the same time

How can I get the action when pressing tow keys at the same time, for example the action when pressing the up and right arrow at the same time.
This example uses JQuery but you should get the idea.
var down = false, right = false;
$(document).keydown(function(e) {
if(e.which == 40) down = true;
if(e.which == 39) right = true;
if(down && right) {
alert("Both keys pressed!");
down = right = false; // required 'cause alert stops 'keyups'
}
});
$(document).keyup(function(e) {
if(e.which == 40) down = false;
if(e.which == 39) right = false;
});

Resources