Closing only particular FancyBox when having multiple Fancybox - fancybox

In a given page, I have multiple instances of Fancybox items that will show up an video when clicked on a link.
Apart from those, I have a function running every 5 seconds to get data from a URL and display another fancybox based on the return value.
The problem is that, as the setInterval function runs always, even if the actual video is played, it closes that video as I use $.fancybox.close().
All I wanted is to close only the fanybox identified by myModal.
This is the jQuery that I use.
$(document).ready(function() {
function myplugin() {
$.getJSON("get-status.php", function (data) {
$.each(data, function (key, status) {
if(status > 0) {
$("#myModal").fancybox().click();
}else{
$.fancybox.close(); // Works. But closes other open Fancybox if any
//$("#myModal").fancybox().close(); // Does not work
}
});
});
};
$(function() {
setInterval(function() { myplugin() }, 5000);
});
});

Well, I am not completely sure I understood your question, however since it's not very easy to know if #myModal is currently opened in fancybox (outside of the fancybox function itself), I would create a flag or switch that would be enabled from within a fancybox callback IF #myModal is the current element opened.
Then, from myplugin() I would validate if the switch is true (#myModal is the current element) and if so, close fancybox.
The script would look something like this (not tested because I don't really know what myplugin() does) :
// declare a switch to set if #myModal is open in fancybox
var myModal = false;
$(document).ready(function () {
function myplugin() {
$.getJSON("get-status.php", function (data) {
$.each(data, function (key, status) {
if (status > 0) {
$("#myModal").fancybox({
// use a callback to set the switch = true
afterShow: function () {
$(this.element).attr("id") == "myModal" ? myModal = true : myModal = false;
}
}).click();
} else {
// close fancybox if myModal == true
if (myModal) {
$.fancybox().close();
myModal = false; // reset switch ?
}
}
});
});
};
// you don't need $(function(){ }); since you have declaread .ready() above
setInterval(function () {
myplugin()
}, 5000);
});

I tried this below one and it worked.
$("#myModal").parents("div .fancybox-skin").hide();
Please advice if there any other better way to do this.

Related

Mapbox GL JS: Style is not done loading

I have a map wher we can classically switch from one style to another, streets to satellite for example.
I want to be informed that the style is loaded to then add a layer.
According to the doc, I tried to wait that the style being loaded to add a layer based on a GEOJson dataset.
That works perfectly when the page is loaded which fires map.on('load') but I get an error when I just change the style, so when adding layer from map.on('styledataloading'), and I even get memory problems in Firefox.
My code is:
mapboxgl.accessToken = 'pk.token';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v10',
center: [5,45.5],
zoom: 7
});
map.on('load', function () {
loadRegionMask();
});
map.on('styledataloading', function (styledata) {
if (map.isStyleLoaded()) {
loadRegionMask();
}
});
$('#typeMap').on('click', function switchLayer(layer) {
var layerId = layer.target.control.id;
switch (layerId) {
case 'streets':
map.setStyle('mapbox://styles/mapbox/' + layerId + '-v10');
break;
case 'satellite':
map.setStyle('mapbox://styles/mapbox/satellite-streets-v9');
break;
}
});
function loadJSON(callback) {
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'regions.json', true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
callback(xobj.responseText);
}
};
xobj.send(null);
}
function loadRegionMask() {
loadJSON(function(response) {
var geoPoints_JSON = JSON.parse(response);
map.addSource("region-boundaries", {
'type': 'geojson',
'data': geoPoints_JSON,
});
map.addLayer({
'id': 'region-fill',
'type': 'fill',
'source': "region-boundaries",
'layout': {},
'paint': {
'fill-color': '#C4633F',
'fill-opacity': 0.5
},
"filter": ["==", "$type", "Polygon"]
});
});
}
And the error is:
Uncaught Error: Style is not done loading
at t._checkLoaded (mapbox-gl.js:308)
at t.addSource (mapbox-gl.js:308)
at e.addSource (mapbox-gl.js:390)
at map.js:92 (map.addSource("region-boundaries",...)
at XMLHttpRequest.xobj.onreadystatechange (map.js:63)
Why do I get this error whereas I call loadRegionMask() after testing that the style is loaded?
1. Listen styledata event to solve your problem
You may need to listen styledata event in your project, since this is the only standard event mentioned in mapbox-gl-js documents, see https://docs.mapbox.com/mapbox-gl-js/api/#map.event:styledata.
You can use it in this way:
map.on('styledata', function() {
addLayer();
});
2. Reasons why you shouldn't use other methods mentioned above
setTimeout may work but is not a recommend way to solve the problem, and you would got unexpected result if your render work is heavy;
style.load is a private event in mapbox, as discussed in issue https://github.com/mapbox/mapbox-gl-js/issues/7579, so we shouldn't listen to it apparently;
.isStyleLoaded() works but can't be called all the time until style is full loaded, you need a listener rather than a judgement method;
Ok, this mapbox issue sucks, but I have a solution
myMap.on('styledata', () => {
const waiting = () => {
if (!myMap.isStyleLoaded()) {
setTimeout(waiting, 200);
} else {
loadMyLayers();
}
};
waiting();
});
I mix both solutions.
I was facing a similar issue and ended up with this solution:
I created a small function that would check if the style was done loading:
// Check if the Mapbox-GL style is loaded.
function checkIfMapboxStyleIsLoaded() {
if (map.isStyleLoaded()) {
return true; // When it is safe to manipulate layers
} else {
return false; // When it is not safe to manipulate layers
}
}
Then whenever I swap or otherwise modify layers in the app I use the function like this:
function swapLayer() {
var check = checkIfMapboxStyleIsLoaded();
if (!check) {
// It's not safe to manipulate layers yet, so wait 200ms and then check again
setTimeout(function() {
swapLayer();
}, 200);
return;
}
// Whew, now it's safe to manipulate layers!
the rest of the swapLayer logic goes here...
}
Use the style.load event. It will trigger once each time a new style loads.
map.on('style.load', function() {
addLayer();
});
My working example:
when I change style
map.setStyle()
I get error Uncaught Error: Style is not done loading
This solved my problem
Do not use map.on("load", loadTiles);
instead use
map.on('styledata', function() {
addLayer();
});
when you change style, map.setStyle(), you must wait for setStyle() finished, then to add other layers.
so far map.setStyle('xxx', callback) Does not allowed. To wait until callback, work around is use map.on("styledata"
map.on("load" not work, if you change map.setStyle(). you will get error: Uncaught Error: Style is not done loading
The current style event structure is broken (at least as of Mapbox GL v1.3.0). If you check map.isStyleLoaded() in the styledata event handler, it always resolves to false:
map.on('styledata', function (e) {
if (map.isStyleLoaded()){
// This never happens...
}
}
My solution is to create a new event called "style_finally_loaded" that gets fired only once, and only when the style has actually loaded:
var checking_style_status = false;
map.on('styledata', function (e) {
if (checking_style_status){
// If already checking style status, bail out
// (important because styledata event may fire multiple times)
return;
} else {
checking_style_status = true;
check_style_status();
}
});
function check_style_status() {
if (map.isStyleLoaded()) {
checking_style_status = false;
map._container.trigger('map_style_finally_loaded');
} else {
// If not yet loaded, repeat check after delay:
setTimeout(function() {check_style_status();}, 200);
return;
}
}
I had the same problem, when adding real estate markers to the map. For the first time addding the markers I wait till the map turns idle. After it was added once I save this in realEstateWasInitialLoaded and just add it afterwards without any waiting. But make sure to reset realEstateWasInitialLoaded to false when changing the base map or something similar.
checkIfRealEstateLayerCanBeAddedAndAdd() {
/* The map must exist and real estates must be ready */
if (this.map && this.realEstates) {
this.map.once('idle', () => {
if (!this.realEstateWasInitialLoaded) {
this.addRealEstatesLayer();
this.realEstateWasInitialLoaded = true
}
})
if(this.realEstateWasInitialLoaded) {
this.addRealEstatesLayer();
}
}
},
I ended up with :
map.once("idle", ()=>{ ... some function here});
In case you have a bunch of stuff you want to do , i would do something like this =>
add them to an array which looks like [{func: function, param: params}], then you have another function which does this:
executeActions(actions) {
actions.forEach((action) => {
action.func(action.params);
});
And at the end you have
this.map.once("idle", () => {
this.executeActions(actionsArray);
});
I have created simple solution. Give 1 second for mapbox to load the style after you set the style and you can draw the layer
map.setStyle(styleUrl);
setTimeout(function(){
reDrawMapSourceAndLayer(); /// your function layer
}, 1000);
when you use map.on('styledataloading') it will trigger couple of time when you changes the style
map.on('styledataloading', () => {
const waiting = () => {
if (!myMap.isStyleLoaded()) {
setTimeout(waiting, 200);
} else {
loadMyLayers();
}
};
waiting();
});

Embedding Facebook Posts Responsive

Facebook claims its embedded posts are adjusted automatically based on the screen sizes.
Please see Can I customize the width of Embedded Posts? section in the below link.
https://developers.facebook.com/docs/plugins/embedded-posts
However, the embed doesn't seem to be responsive. Please see my test here,
http://colombowebs.com/test/fb/
Is there anything I have to do in addition to make it responsive?
You have to use javascript/jquery to obtain the desired result. I have taken help from responsive function and created the following which works almost for all widths.
(function ($) {
jQuery.fn.autoResizeFbPost = function () {
var fixWidth = function ($container, $clonedContainer, doParse) {
// default parameter.
doParse = typeof doParse == 'undefined' ? true : doParse;
var updatedWidth = $container.width();
// update all div.fb-post with correct width of container
var isMobile = window.matchMedia("only screen and (max-width: 600px)");
if (isMobile.matches) {
//Conditional script here
if (window.matchMedia("(orientation: portrait)").matches) {
// you're in PORTRAIT mode
updatedWidth = $(window).width();
}
if (window.matchMedia("(orientation: landscape)").matches) {
// you're in LANDSCAPE mode
updatedWidth = $(window).height();
}
}
$clonedContainer
.find('div.fb-post')
.each(function () {
$(this).attr('data-width', updatedWidth);
});
$('div.embedded', $clonedContainer).each(function () {
$(this).attr('max-width', updatedWidth);
});
// update page with adjusted markup
$container.html($clonedContainer.html());
//should we call FB.XFBML.parse? we don't want to do this at page load because it will happen automatically
if (doParse && FB && FB.XFBML && FB.XFBML.parse)
FB.XFBML.parse();
};
return this.each(function () {
var $container = $(this),
$clonedContainer = $container.clone();
// make sure there is a .fb-post element before we do anything.
if (!$container.find('div.fb-post').length) {
return false;
}
// execute once (document.ready) and do not call FB.XFBML.parse()
fixWidth($container, $clonedContainer, false);
$(window).bind('resize', function () {
fixWidth($container, $clonedContainer);
}).trigger('resize');
});
};
})(jQuery);
(function ($) {
$(document).ready(function () {
$('#post').autoResizeFbPost();
});
})(jQuery);
And your HTML should be like
<div style="background-color: white;" id="post">
<div class="fb-post" data-href="your-facebook-post-url" mobile="false"></div>
Hope this helps you. Feel free to post your comments.

How do I trigger tinymce 4.x focus and blur events

I realize that this question has been asked and answered several times, but I still can't make many of the solutions work. It seems like most of the discussions are older and maybe not compatible with 4.x.
My goal: be able fire some javascript functions upon focus or blur. Here's the base code:
$('.tiny-mce').tinymce({
script_url : '/xm_js/tinymce4/tinymce.min.js',
});
I tried examples like:
$('.tiny-mce').tinymce({
script_url : '/xm_js/tinymce4/tinymce.min.js',
setup : function(ed) {
ed.onInit.add(function(ed, evt) {
var dom = ed.dom;
var doc = ed.getDoc();
tinymce.dom.Event.add(doc, 'blur', function(e) {
alert('blur!!!');
});
});
}
});
returns:"Uncaught TypeError: Cannot call method 'add' of undefined"
$('.tiny-mce').tinymce({
script_url : '/xm_js/tinymce4/tinymce.min.js',
});
tinymce.activeEditor.on('focus', function(e) {
console.log(e.blurredEditor);
});
returns: "Uncaught TypeError: Cannot call method 'on' of undefined"
(but not sure if I have it in the right place)
$('.tiny-mce').tinymce({
script_url : '/xm_js/tinymce4/tinymce.min.js',
setup: function(editor) {
editor.on('focus', function(e) {
console.log('focus event', e);
});
}
});
returns: "Uncaught SyntaxError: Unexpected identifier"
This works but only when initiating the editor. Other things I've tried but haven't gotten to work:
tinymce.FocusManager
tinymce.activeEditor
What am I missing? Thanks.
UPDATE: found a solution that worked beautifully: Why TinyMCE get focus and blur event, when user jump from other input field?
see the fiddle at http://fiddle.tinymce.com/8Xeaab/1
tinymce.init({
selector: "#editme",
inline: true,
setup: function(editor) {
editor.on('focus', function(e) {
console.log("focus");
});
editor.on('blur', function(e) {
console.log("blur");
});
}
});
Your cuestion title its about TRIGGERING focus and blur events, but you really are asking about HANDLING those events.
If anybody is still looking for triggering the events, the solution should by:
tinymce.init({
selector: "#textarea_123",
...
});
then, to set focus:
var inst = tinyMCE.EditorManager.get('textarea_123');
inst.focus();
I recently ran into this issue and although I am doing this in angularjs I was able to implement a fix for it by creating a directive that registers when you click off of it and then clears the activeElement in the html body. I will add the directive below. You just call it on the object by adding click-off like you would an ng-cloak to a tag.
(function () {
'user strict';
angular.module('app.directives').directive('clickOff', ClickOff);
function ClickOff($parse, $document) {
var directive = {
link: link
};
return directive;
function link(scope, $element, attr) {
var fn = $parse(attr["clickOff"]);
$element.bind('click', function (event) {
event.stopPropagation();
});
angular.element($document[0].body).bind("click", function (event) {
scope.$apply(function () {
$document[0].activeElement.blur();
fn(scope, { $event: event });
});
});
}
}
})();

jqgrid display editform (the entire form) based on dataURL result

I am using form editing but I only want the ADD form to appear if the results from dataURL are correct. I can hide it, but I really don't want it at all on condition. Plus, the hide() only works after the alert is cleared
$("#schedule").jqGrid('editGridRow', "new", {
url: './ar_schedule_update.cgi?',
editData: {visitor:visitor},
beforeInitData: function() {
$('#schedule').setColProp('archiveid',{editable: true,hidden:false, edittype: 'select',
editoptions: {dataUrl: './ar_archiveid_edit_options.cgi?system=' + selected_system,
buildSelect: function(data) {
if (data.match(/^ERROR/)) {
$('#editmodschedule').hide(); //Makes it disappear ok after alert cleared
alert(data);
return false;
}
return data;
}
}
});
},
beforeShowForm: function(formid) {
//NEED TO EVALUATE CONDITION HERE? AND BAIL IF ERROR
},
onClose: function() {...............
Thanks in advance,
Mike

How to access old and new values before submitting with jeditable

I have a field being updated by jeditable. I want to output a warning message before submitting updates if the value is being reduced (which would result in data being lost), but not if it's being increased.
This seems a good candidate for jeditable's onsubmit function, which I can trigger happily. I can get the new value from $('input', this).val(), but how do I get the original value to which to compare it in this context?
...
Since posting the above explanation / question, I've come up with a solution of sorts. By changing the invokation in jquery.ready from
$('#foo').editable(...);
to
$('#foo').hover(function(){
var old_value = $(this).text();
$(this).editable('ajax.php', {
submitdata {'old_value':old_value}
});
});
I can use settings.submitdata.old_value in the onsubmit method.
But there surely has to be a better way? jeditable must still have the old value tucked away somewhere in order to be able to revert it. So the question becomes how can I access that from the onsubmit function?
Many thanks in advance for any suggestions.
A much easier solution would be to add this line to your submitdata variable
"submitdata": function (value, settings) {
return {
"origValue": this.revert
};
}
Here is my editable (it is using the submitEdit function):
$(function () {
$('.editable').editable(submitEdit, {
indicator: '<img src="content/images/busy.gif">',
tooltip: '#Html.Resource("Strings,edit")',
cancel: '#Html.Resource("Strings,cancel")',
submit: '#Html.Resource("Strings,ok")',
event: 'edit'
});
/* Find and trigger "edit" event on correct Jeditable instance. */
$(".edit_trigger").bind("click", function () {
$(this).parent().prev().trigger("edit");
});
});
In submitEdit origvalue is the original value before the edit
function submitEdit(value, settings) {
var edits = new Object();
var origvalue = this.revert;
var textbox = this;
var result = value;
// sb experiment
var form = $(this).parents('form:first');
// end experiment
edits["field"] = form.find('input[name="field"]').val();
edits["value"] = value;
var returned = $.ajax({
url: '#Url.Action("AjaxUpdate")',
type: "POST",
data: edits,
dataType: "json",
complete: function (xhr, textStatus) {
// sever returned error?
// ajax failed?
if (textStatus != "success") {
$(textbox).html(origvalue);
alert('Request failed');
return;
}
var obj = jQuery.parseJSON(xhr.responseText);
if (obj != null && obj.responseText != null) {
alert(obj.responseText);
$(textbox).html(origvalue);
}
}
});
return (result);
}