Mapbox GL Menu Doesn't Respond to First Click - visibility

Similar to this question, the layer switcher in my Map does not react to the first click. I learned that this issue has something to do with the definition of the initial visibility on the layers.
Here is the code. Unfortunately I don't know how and where to insert default visibility - do you have an idea?
map.on('click', ({ point }) => {
const features = map.queryRenderedFeatures(point, {
layers: ['City'] // replace with your layer name
});
if (!features.length) {
return;
}
const feature = features[0]; const popup = new mapboxgl.Popup({offset: [0, -15], closeButton: false, closeOnMove: true})
.setMaxWidth("auto")
.setLngLat(feature.geometry.coordinates)
.setHTML(
`<table>\
<tr>\
<td>City</td>\
<td>${feature.properties.City}</td>
</tr>\ </table>`
)
.addTo(map); }); var toggleableLayerIds = ['City']
for (var i = 0; i < toggleableLayerIds.length; i++) {
var id = toggleableLayerIds[i]
var link = document.createElement('a')
link.href = '#'
link.className = 'active'
link.textContent = id
link.onclick = function (e) {
var clickedLayer = this.textContent
e.preventDefault()
e.stopPropagation()
var visibility = map.getLayoutProperty(clickedLayer, 'visibility')
if (visibility === 'visible') {
map.setLayoutProperty(clickedLayer, 'visibility', 'none')
this.className = ''
} else {
this.className = 'active'
map.setLayoutProperty(clickedLayer, 'visibility', 'visible')
}
}
var layers = document.getElementById('menu')
layers.appendChild(link)
}

Related

Ckeditor scrollbar marker / Text Position Indicator

I would like to implement scrollbar marker into ckeditor and i can't seem to find the right way to do it i have triyed this code
var win = new CKEDITOR.dom.window( window );
var pos = win.getScrollPosition();
console.log(pos);
but it only return the google chrome scrollbar x=0 & Y=0
var win = new CKEDITOR.dom.window( domWindow );
var pos = win.getScrollPosition();
console.log(pos);
and this give me an error domWindow is not defined
i found this example it may help: https://codepen.io/Rplus/pen/mEjWJm
(() => {
var containerQS = '.article';
var container = document.querySelector(containerQS);
var form = document.querySelector('.form');
var input = form.querySelector('input[type="text"]');
var markClass = 'mark';
var markerHeight = '2px';
var _color = 'currentColor';
var containerY = container.offsetTop;
var containerH = container.scrollHeight;
var customStyle = document.createElement('style');
container.appendChild(customStyle);
var renderScrollMarker = ($parent, posArr) => {
var _posArr = posArr.map(i => {
return `transparent ${i}, ${_color} ${i}, ${_color} calc(${i} +
${markerHeight}), transparent calc(${i} + ${markerHeight})`;
});
customStyle.innerHTML = `article::-webkit-scrollbar-track {
background-image: linear-gradient(${_posArr.join()});
}`;
};
var calcEleRelativePos = ($ele) => {
return ($ele.offsetTop - containerY) / containerH;
};
var markOpt = {
className: markClass,
done: function () {
var marks = document.querySelectorAll(`.${markClass}`);
var allY = [].map.call(marks, (mark) => {
return (calcEleRelativePos(mark) * 100).toFixed(2) + '%';
});
renderScrollMarker(container, allY);
console.log(allY);
}
};
var instance = new Mark(container);
form.addEventListener('submit', (e) => {
e.preventDefault();
var _text = input.value.trim();
console.log(_text, form.oldText);
if (_text === '') {
instance.unmark(markOpt);
return;
}
form.oldText = _text;
instance.unmark().mark(_text, markOpt);
});
// trigger
form.querySelector('input[type="submit"]').click();
})();
but as ckeditor secures a lot of element, i would love to know if any one has done this before with CKeditor
i just got the real editor scrollbar position, i only need to put a marker using style or any availble methode
var win=CKEDITOR.instances.editor1.document.getWindow();
var pos = win.getScrollPosition().y;
console.log(pos);
this worked for me :
var jqDocument = $(editor.document.$);
var documentHeight = jqDocument.height();
var scrollTo =jqDocument.scrollTop();
var docHeight = jqDocument.height();
var scrollPercent = (scroll)/(docHeight);
var scrollPercentRounded = Math.round(scrollPercent*100);
$(".ui-slider-handle").css("bottom", 100-scrollPercentRounded+"%");

OpenLayers3 : Draggable OverviewMapControl

In OpenLayers 2, in the OverviewMapControl, you can drag the "box" to move the map.
You can not do this in OpenLayers 3.
I've tried to implement a custom control based on https://github.com/openlayers/ol3/blob/master/src/ol/control/overviewmapcontrol.js, but you can not use goog.xxx or other fancy stuff like ol.extent.scaleFromCenter when you are not in debug !
How should I proceed ?
basically, implementing drag'n drop is fairly "simple" :
var dragging = null;
var getMap = this.getMap.bind(this); //during ctor of a control, we have no access to the map !
$(document.body).on("mousemove", function (e) {
if (dragging) {
dragging.el.offset({
top: e.pageY,
left: e.pageX
});
}
});
$(box).on("mousedown", function (e) {
dragging = {
el: $(e.target)
};
});
$(document.body).on("mouseup", function (e) {
if (dragging) {
debugger;
var coords = ovmap.getEventCoordinate(e.originalEvent);
//TODO: taking event coordinates is not good, we must use center of the box coordinates
//the problem is that ovmap.getCoordinateFromPixel(dragging.el.offset()) is not working at all because we need to adjust ovmap viewport
getMap().getView().setCenter(coords);
dragging = null;
}
});
For those interested (which does not seem to be the case at the moment :)), here is the way I solved
/**
* Mostly a big copy/paste from https://raw.githubusercontent.com/openlayers/ol3/master/src/ol/control/overviewmapcontrol.js
* without rotation and zoom/dezoom plus some adapations from http://ol3.qtibia.ro/build/examples/overviewmap-custom-drag.html
* to add the possibility to drag the box on the minimap to move the main map
*/
ol.control.CustomOverviewMap = function (opt_options) {
var options = typeof opt_options !== 'undefined' ? opt_options : {};
this.collapsed_ = typeof options.collapsed !== 'undefined' ? options.collapsed : true;
this.onCollapseOrExpand = options.onCollapseOrExpand || function () { };
this.needFirstRenderUpdate_ = this.collapsed_; //prepare the hack to render the map when uncollapsed the first time
var tipLabel = typeof options.tipLabel !== 'undefined' ? options.tipLabel : 'Overview map';
this.collapseLabel_ = $('<span>\u00BB</span>').get(0);
this.label_ = $('<span>\u00AB</span>').get(0);
var activeLabel = (!this.collapsed_) ? this.collapseLabel_ : this.label_;
var button = $('<button type="button" title="{0}"></button>'.replace('{0}', tipLabel)).append(activeLabel);
button.on('click', this.handleClick_.bind(this));
//ol.control.Control.bindMouseOutFocusOutBlur(button);
button.on('mouseout', function () { this.blur(); });
button.on('focusout', function () { this.blur(); });
var ovmapDiv = $('<div class="ol-overviewmap-map"></div>').get(0);
this.ovmap_ = new ol.Map({
controls: new ol.Collection(),
interactions: new ol.Collection(),
layers: [options.tileLayer],
target: ovmapDiv,
view: new ol.View(opt_options.view)
});
var box = $('<div class="ol-overviewmap-box"></div>');
this.boxOverlay_ = new ol.Overlay({
position: [0, 0],
positioning: 'bottom-left',
element: box.get(0)
});
this.ovmap_.addOverlay(this.boxOverlay_);
var cssClasses = 'ol-overviewmap ol-unselectable ol-control' +
(this.collapsed_ ? ' ol-collapsed' : '');
var element = $('<div class="{0}"></div>'.replace('{0}', cssClasses)).append(ovmapDiv).append(button).get(0);
ol.control.Control.call(this, {
element: element,
render: ol.control.CustomOverviewMap.render
});
// deal with dragable minimap
this.dragging = null;
box.on("mousedown", this.onStartDrag.bind(this));
$(document.body).on("mousemove", this.onDrag.bind(this));
$(document.body).on("mouseup", this.onEndDrag.bind(this));
};
ol.inherits(ol.control.CustomOverviewMap, ol.control.Control);
ol.control.CustomOverviewMap.prototype.onStartDrag = function (e) {
// remember some data to use during onDrag or onDragEnd
var box = $(e.target);
this.dragging = {
el: box,
evPos: { top: e.pageY, left: e.pageX },
elPos: box.offset()
};
}
ol.control.CustomOverviewMap.prototype.onDrag = function (e) {
if (this.dragging) {
//set the position of the box to be oldPos+translation(ev)
var curOffset = this.dragging.el.offset();
var newOffset = {
top: curOffset.top + (e.pageY - this.dragging.evPos.top),
left: curOffset.left + (e.pageX - this.dragging.evPos.left)
};
this.dragging.evPos = { top: e.pageY, left: e.pageX };
this.dragging.el.offset(newOffset);
}
}
ol.control.CustomOverviewMap.prototype.onEndDrag = function (e) {
if (this.dragging) {
//see ol3.qtibia.ro href at the top of the class to understand this
var map = this.getMap();
var offset = this.dragging.el.position();
var divSize = [this.dragging.el.width(), this.dragging.el.height()];
var mapSize = map.getSize();
var c = map.getView().getResolution();
var xMove = offset.left * (Math.abs(mapSize[0] / divSize[0]));
var yMove = offset.top * (Math.abs(mapSize[1] / divSize[1]));
var bottomLeft = [0 + xMove, mapSize[1] + yMove];
var topRight = [mapSize[0] + xMove, 0 + yMove];
var left = map.getCoordinateFromPixel(bottomLeft);
var top = map.getCoordinateFromPixel(topRight);
var extent = [left[0], left[1], top[0], top[1]];
map.getView().fitExtent(extent, map.getSize());
map.getView().setResolution(c);
//reset the element at the original position so that when the main map will trigger
//the moveend event, this event will be replayed on the box of the minimap
this.dragging.el.offset(this.dragging.elPos);
this.dragging = null;
}
}
ol.control.CustomOverviewMap.render = function (mapEvent) {
//see original OverviewMap href at the top of the class to understand this
var map = this.getMap();
var ovmap = this.ovmap_;
var mapSize = map.getSize();
var view = map.getView();
var ovview = ovmap.getView();
var overlay = this.boxOverlay_;
var box = this.boxOverlay_.getElement();
var extent = view.calculateExtent(mapSize);
var ovresolution = ovview.getResolution();
var bottomLeft = ol.extent.getBottomLeft(extent);
var topRight = ol.extent.getTopRight(extent);
overlay.setPosition(bottomLeft);
// set box size calculated from map extent size and overview map resolution
if (box) {
var boxWidth = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution);
var boxHeight = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution);
$(box).width(boxWidth).height(boxHeight);
}
};
ol.control.CustomOverviewMap.prototype.handleClick_ = function (event) {
event.preventDefault();
this.collapsed_ = !this.collapsed_;
$(this.element).toggleClass('ol-collapsed');
// change label
if (this.collapsed_) {
this.collapseLabel_.parentNode.replaceChild(this.label_, this.collapseLabel_);
} else {
this.label_.parentNode.replaceChild(this.collapseLabel_, this.label_);
}
// manage overview map if it had not been rendered before and control is expanded
if (!this.collapsed_ && this.needFirstRenderUpdate_) {
this.needFirstRenderUpdate_ = false;
this.ovmap_.updateSize();
this.ovmap_.once("postrender", function () {
this.render();
}.bind(this));
}
//trigger event
this.onCollapseOrExpand(this.collapsed_);
};

Vertical and horizontal scrollable ion-content with ion-infinite-scroll only vertically

Inside my ion-content I have a list which when scrolled to the bottom more items are loaded (provided by ion-infinite-scroll which calls 'LoadMore()').
The problem is that if I set direction = xy to ion-content, ion-infinite-scroll calls 'LoadMore()' if I scroll vertically and horizontally.
It is possible to my ion-infinite-scroll only call 'LoadMore()' when scrolled vertically?
Currently ionic version beta.13 does not support this feature.
I already have posted my suggested solution on ionic repository ( https://github.com/driftyco/ionic/issues/1073 )
I've created 'ion-infinite-scroll-fixed' directive wich differs only in last if block:
.directive('ionInfiniteScrollFixed', ['$timeout', function($timeout) {
function calculateMaxValue(distance, maximum, isPercent) {
return isPercent ?
maximum * (1 - parseFloat(distance,10) / 100) :
maximum - parseFloat(distance, 10);
}
return {
restrict: 'E',
require: ['^$ionicScroll', 'ionInfiniteScrollFixed'],
template: '<i class="icon {{icon()}} icon-refreshing"></i>',
scope: true,
controller: ['$scope', '$attrs', function($scope, $attrs) {
this.isLoading = false;
this.scrollView = null; //given by link function
this.getMaxScroll = function() {
var distance = ($attrs.distance || '2.5%').trim();
var isPercent = distance.indexOf('%') !== -1;
var maxValues = this.scrollView.getScrollMax();
return {
left: this.scrollView.options.scrollingX ?
calculateMaxValue(distance, maxValues.left, isPercent) :
-1,
top: this.scrollView.options.scrollingY ?
calculateMaxValue(distance, maxValues.top, isPercent) :
-1
};
};
}],
link: function($scope, $element, $attrs, ctrls) {
var scrollCtrl = ctrls[0];
var infiniteScrollCtrl = ctrls[1];
var scrollView = infiniteScrollCtrl.scrollView = scrollCtrl.scrollView;
$scope.icon = function() {
return angular.isDefined($attrs.icon) ? $attrs.icon : 'ion-loading-d';
};
var onInfinite = function() {
$element[0].classList.add('active');
infiniteScrollCtrl.isLoading = true;
$scope.$parent && $scope.$parent.$apply($attrs.onInfinite || '');
};
var finishInfiniteScroll = function() {
$element[0].classList.remove('active');
$timeout(function() {
scrollView.resize();
checkBounds();
}, 0, false);
infiniteScrollCtrl.isLoading = false;
};
$scope.$on('scroll.infiniteScrollComplete', function() {
finishInfiniteScroll();
});
$scope.$on('$destroy', function() {
void 0;
if(scrollCtrl && scrollCtrl.$element)scrollCtrl.$element.off('scroll', checkBounds);
});
var checkBounds = ionic.animationFrameThrottle(checkInfiniteBounds);
//Check bounds on start, after scrollView is fully rendered
setTimeout(checkBounds);
scrollCtrl.$element.on('scroll', checkBounds);
function checkInfiniteBounds() {
if (infiniteScrollCtrl.isLoading) return;
var scrollValues = scrollView.getValues();
var maxScroll = infiniteScrollCtrl.getMaxScroll();
if ((maxScroll.left !== -1 && scrollValues.left >= maxScroll.left && $attrs.notOnHorizontal !=="true") ||
(maxScroll.top !== -1 && scrollValues.top >= maxScroll.top && $attrs.notOnVertical !=="true")) {
onInfinite();
}
}
}
};
}]);
and in my HTML:
<ion-infinite-scroll-fixed
not-on-horizontal="true"
ng-if="infiniteScroll.canLoad"
on-infinite="infiniteScroll.loadMore();"
distance="1%">
</ion-infinite-scroll-fixed>
I hope this can help somebody :)

WordPress remove manual Ajax trigger and use infinite scroll

I have a problem with my script. I want to remove the load more button and instead do an infinite scroll when I get to bottom of the page.
I'm using a WordPress template and without support I'm stuck on this nonsense.
What should I change to do to this script?
jQuery(document).ready(function($){
var $container = $('#hentry-wrapper');
// Isotope
// modified Isotope methods for gutters in masonry
$.Isotope.prototype._getMasonryGutterColumns = function() {
var gutter = this.options.masonry && this.options.masonry.gutterWidth || 0;
containerWidth = this.element.width();
this.masonry.columnWidth = this.options.masonry && this.options.masonry.columnWidth ||
// or use the size of the first item
this.$filteredAtoms.outerWidth(true) ||
// if there's no items, use size of container
containerWidth;
this.masonry.columnWidth += gutter;
this.masonry.cols = Math.floor( ( containerWidth + gutter ) / this.masonry.columnWidth );
this.masonry.cols = Math.max( this.masonry.cols, 1 );
};
$.Isotope.prototype._masonryReset = function() {
// layout-specific props
this.masonry = {};
// FIXME shouldn't have to call this again
this._getMasonryGutterColumns();
var i = this.masonry.cols;
this.masonry.colYs = [];
while (i--) {
this.masonry.colYs.push( 0 );
}
};
$.Isotope.prototype._masonryResizeChanged = function() {
var prevSegments = this.masonry.cols;
// update cols/rows
this._getMasonryGutterColumns();
// return if updated cols/rows is not equal to previous
return ( this.masonry.cols !== prevSegments );
};
var loadMore = $('#load-more');
var posts_per_page = parseInt(loadMore.attr('data-perpage'));
var offset = posts_per_page;
var totalPosts = parseInt(loadMore.attr('data-total-posts'));
var author = parseInt(loadMore.attr('data-author'));
var category = parseInt(loadMore.attr('data-category'));
var tag = loadMore.attr('data-tag');
var datemonth = loadMore.attr('data-month');
var dateyear = loadMore.attr('data-year');
var search = loadMore.attr('data-search');
var loader = $('#posts-count').attr('data-loader');
if (!author) author = 0;
if (!category) category = 0;
if (!tag) tag = '';
if (!datemonth) datemonth = 0;
if (!dateyear) dateyear = 0;
if (!search) search = '';
// cache jQuery window
var $window = $(window);
// start up isotope with default settings
$(window).load(function(){
reLayout();
$window.smartresize( reLayout );
if (offset < totalPosts) {
$('#nav-pagination-load-more').fadeIn(200);
mega_initLoadMore();
}
});
function reLayout() {
var mediaQueryId = getComputedStyle( document.body, ':after' ).getPropertyValue('content');
// fix for firefox, remove double quotes "
//mediaQueryId = mediaQueryId.replace( /"/g, '' );
//console.log( mediaQueryId );
var windowSize = $window.width();
var masonryOpts;
// update sizing options
switch ( mediaQueryId ) {
case 'large' :
masonryOpts = {
gutterWidth: 0
};
break;
case 'big' :
masonryOpts = {
//columnWidth: 297,
gutterWidth: 0
};
break;
case 'medium' :
masonryOpts = {
//columnWidth: 269,
gutterWidth: 0
};
break;
case 'small' :
masonryOpts = {
//columnWidth: $container.width() / 4,
gutterWidth: 0
};
break;
case 'tiny' :
masonryOpts = {
//columnWidth: $container.width() / 1,
gutterWidth: 0
};
break;
}
$container.isotope({
resizable: false, // disable resizing by default, we'll trigger it manually
itemSelector : '.type-post',
transformsEnabled: false, // Firefox Vimeo issue
masonry: masonryOpts
}).isotope( 'reLayout' );
}
function mega_initLoadMore(){
loadMore.click(function(e) {
$(this).unbind("click").addClass('active');
$('#posts-count').html('<img src="'+ loader +'"/>');
e.preventDefault();
mega_loadMorePosts();
});
}
function mega_reLayout(){
$container.isotope( 'reLayout' );
}
function mega_loadMorePosts(){
jQuery.ajax({
url: megaAjax.ajaxurl,
type: 'POST',
data: {
action : 'mega_ajax_blog',
nonce : megaAjax.nonce,
category: category,
author: author,
tag: tag,
datemonth: datemonth,
dateyear: dateyear,
search: search,
offset: offset
},
success: function( data ) {
var $newElems = $(data);
// ensure that images load before adding to masonry layout
$newElems.imagesLoaded( function(){
// FitVids
$('.fluid-video, .entry-content', $newElems).fitVids();
$container.append($newElems).isotope( 'appended', $newElems );
// Flex Slider
$('.flexslider', $newElems).flexslider({
animation: "fade",
slideshow: false,
keyboard: false,
directionNav: true,
touch: true,
prevText: "",
nextText: ""
});
setTimeout(function(){
mega_reLayout();
}, 1000);
offset = offset + posts_per_page;
loadMore.removeClass('active');
if (offset < totalPosts){
$('#posts-count').text('');
loadMore.bind("click", mega_initLoadMore());
}
else {
setTimeout(function(){
loadMore.parent().remove();
}, 1000 );
}
});
}
});
return false;
}
});
I think this script is taken from "HEAT WORDPRESS THEME" directly which is located in js folder of the theme. Its simple to modify,you just need to remove Ajax post loading function and keep Isotop initializing function only. For help see this link
http://www.shambix.com/en/isotope-twitter-bootstrap-infinite-scroll-fluid-responsive-layout/

Ajax client object method invoking with parameter

Inside client control I generate a button, with script to run.
I want to call object's Print() method when this button is clicked, the result value must be passed to Print() as well.
How can I do that?
This is my object:
Type.registerNamespace("CustomControls");
CustomControls.FirstObj = function(element) {
CustomControls.FirstObj.initializeBase(this, [element]);
this._targetControlDelegate === null
this.markUp = '<div><input type="button" id="theButton" value="Button!" onclick="Foo()"/><script type="text/javascript">function Foo() {return "result";}</script></div>';
}
CustomControls.FirstObj.prototype = {
dispose: function() {
CustomControls.FirstObj.callBaseMethod(this, 'dispose');
},
initialize: function() {
var div;
div = document.createElement('div');
div.name = div.id = "divName";
div.innerHTML = this.markUp;
document.body.appendChild(div);
var targetControl = $get("theButton");
// if (targetControl != null) {
// if (this._targetControlDelegate === null) {
// this._targetControlDelegate = Function.createDelegate(this, this._targetControlHandler);
// }
// Sys.UI.DomEvent.addHandler(targetControl, 'click', this._targetControlDelegate);
// }
CustomControls.FirstObj.callBaseMethod(this, 'initialize');
},
// _targetControlHandler: function(event) {
//
//
// },
_Print: function(result) {
//Alert Result
},
}
CustomControls.FirstObj.registerClass('CustomControls.FirstObj', Sys.UI.Control);
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Update:
I guess there is no solution for my problem.
Maybe there is an alternative approach that you can suggest?
One way would be to store the FirstObj object in a property of the button it just created:
initialize: function() {
var div = document.createElement("div");
div.name = div.id = "divName";
div.innerHTML = this.markUp;
document.body.appendChild(div);
var targetControl = $get("theButton");
targetControl.__firstObj = this;
CustomControls.FirstObj.callBaseMethod(this, 'initialize');
}
That would allow you to use that property to refer to the FirstObj object inside your markup:
CustomControls.FirstObj = function(element) {
CustomControls.FirstObj.initializeBase(this, [element]);
this._targetControlDelegate = null;
this.markUp = '<div><input type="button" id="theButton" value="Button!"'
+ 'onclick="this.__firstObj._Print(Foo());" />'
+ '<script type="text/javascript">function Foo() {return "result";}'
+ '</script></div>';
}

Resources