Qtip hide on destroy, show on hover, Dom cleaning like bootstrap tooltip - javascript

I am using jquery qtip2
I want its behaviour just like bootstrap tooltips where
on hover tooltip shows up , also in DOM
on mouseout tooltip hides, removed from DOM as well
Objective:
My objective is I am using lots of qtips, and they are taking unnecessary space in DOM and I want qtip2 to create dom element only when it is active.
JSFIDDLE: https://jsfiddle.net/bababalcksheep/5unavg0q/4/
Can't seem to make it work.Should it not be feature by default. Am I missing something from Docs ?
HTML:
Hover here!
JS:
$(document).ready(function() {
$('.qtiptxt').qtip({
prerender: false,
overwrite: true,
hide: {
event: 'mouseout'
},
events: {
hide: function(event, api) {
var target = api.elements.target;
var targetOptions = api.options;
// Destroy it immediately
api.destroy(true);
//re initialize using existing options
$(target).qtip(targetOptions);
}
}
});
});

It seems I did miss the docs. Here is the solution
https://jsfiddle.net/bababalcksheep/5unavg0q/7/
$(document).ready(function() {
//
// from https://github.com/qTip2/qTip2/wiki/Events-Guide#delegation-on--live--delegate
//
$('.qtiptxt').on('mouseover', function(event) {
$(this).qtip({
prerender: false,
overwrite: true,
show: {
event: event.type,
ready: true
},
hide: {
event: 'mouseout'
},
events: {
hidden: function(event, api) {
// Destroy it immediately
api.destroy(true);
}
}
}, event);
});
//
//
});

Related

Is it possible to call the tippy (js) constructor only on the newest added popover?

after I created the popovers I am calling the tippy() constructor like:
tippy('.my-tippy-popover', { ... }); But this is creating all existing tippy popovers again. So if you have 80 popovers and you add a new one, then the tippy() constructor is creating 81 new popovers. And if you click one of the popovers you get 2x the event e.g. onShow. If you add now again a new popover and run tippy() constructor and click after that a popover, you get 3x onShow event. And so on. So it's adding more and more event listeners.
How can I avoid that?
Edit jsfiddle
jQuery(($) => {
runTippy()
})
function runTippy() {
tippy('.my-tippy-popover', {
content(reference) {
const id = reference.getAttribute('data-template');
const template = document.getElementById(id);
return template.innerHTML;
},
onHide(instance) {
console.log('+++ tippy onHide +++')
},
onCreate(instance) {
console.log('+++ tippy onCreate +++')
},
onShow(instance) {
console.log('+++ tippy onShow +++')
},
onShown(instance) {
console.log('+++ tippy onShown +++')
},
allowHTML: true,
trigger: 'click',
appendTo: document.getElementById('tippy-container'),
interactive: true,
interactiveBorder: 10,
interactiveDebounce: 35,
maxWidth: 'none',
});
}
function addPopover() {
const body = $('body');
body.append(`<span class="my-tippy-popover" data-template="tippyContent" >Popover</span><br>`);
runTippy()
}

Semantic-ui popup Dynamic content

Semantic-ui ver. 2.0.8.
I currently use the following method to load dynamic content in a pop-up
JAVASCRIPT
var popupContent = null;
var popupLoading = '<i class="notched circle loading icon green"></i> wait...';
$('.vt').popup({
inline: true,
on: 'hover',
exclusive: true,
hoverable: true,
html: popupLoading,
variation: 'wide',
delay: {
show: 400,
hide: 400
},
onShow: function(el) { // load data (it could be called in an external function.)
var then = function(r) {
if (r.status) {
popupContent = r.data; // html string
} else {
// error
}
};
var data = {
id: el.dataset.id
};
ajax.data('http://example.site', data, then); // my custom $.ajax call
},
onVisible: function(el) { // replace popup content
this.html(popupUserVoteContent);
},
onHide: function(el) { // replace content with loading
this.html(popupLoading);
}
});
HTML
<h2 data-id="123" class="vt">10</h2>
<div class="ui popup" data-id="123"></div>
There 's a way to simplify the whole process?
For example with a element.popup ('refresh') after loading the new content?
I tried:
JAVASCRIPT
...
if (r.status) {
$('.ui.popup[data-id="123"]').html(r.data);
}
...
but it does not work.
I also tried using (replace) data-content into h2.vt but nothing.
The only improvement that comes to mind is to make the code a little cleaner (you only really need the onShow event, which fires before the popup shows) and avoid using a global variable (popupContent).
That said, the main idea is mostly the same - when the popup is supposed to show, you replace its content with some fake content (the loading animation), then trigger $.ajax and update the popup content as soon as the request completes.
var popupLoading = '<i class="notched circle loading icon green"></i> wait...';
$('.vt').popup({
inline: true,
on: 'hover',
exclusive: true,
hoverable: true,
html: popupLoading,
variation: 'wide',
delay: {
show: 400,
hide: 400
},
onShow: function (el) { // load data (it could be called in an external function.)
var popup = this;
popup.html(popupLoading);
$.ajax({
url: 'http://www.example.com/'
}).done(function(result) {
popup.html(result);
}).fail(function() {
popup.html('error');
});
}
});

Marionette: can you use the same event configuration for a trigger and an event?

If I set up a Marionette view using the same event configuration for both a trigger and an event, only the trigger seems to get fired. Here's a simplified example: clicking .button should run show and trigger the select:something event. However, it only triggers the event.
var MyView = Marionette.CompositeView.extend({
ui: {
'button': '.button'
},
triggers: {
'click .button': 'select:something',
},
events: {
'click .button': 'show'
},
show: function() {
// won't fire
}
});
var view = new MyView({});
view.on('select:something', handleSelect); // will fire
The Marionette trigger docs suggested that setting stopPropogation to false would help, but that didn't change the behavior for me:
triggers: {
'click .button': {
event: "select:something",
preventDefault: true,
stopPropagation: false
}
}, ...
Marionette.View delegateEvents codes is:
// behavior events will be overriden by view events and or triggers
_.extend(combinedEvents, behaviorEvents, events, triggers, behaviorTriggers);
Backbone.View.prototype.delegateEvents.call(this, combinedEvents);
Events will be overriden by triggers because that events hash is before triggers hash in _.extend.
You could use different key in events and triggers hash. The code like this:
var viewtemplate = _.template('<button class="button show-btn">show</button>');
var MyView = Marionette.CompositeView.extend({
template: viewtemplate,
triggers: {
'click .button': 'select:something',
},
events: {
'click .show-btn': 'show'
},
show: function() {
console.log('click .show-btn');
}
});

jQuery does not work when reload the page content via ajax

I use Bootstrap to display a popover, until there is with all this code below everything works normal.
$(".emoticons").popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {return $('.emoticonimg').html();
}
});
I only need to load the content of the page via ajax, then I changed the code because when I load the content dynamically I need to delegate events, changed the code and it looked like this:
$('body').on('click','.emoticons',function()
{
$(".emoticons").popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {return $('.emoticonimg').html();
}
});
});
Now my troubles started. The code works however when I click the first time it does not work, so it works when I click more than once on the link. What to do?
What's happening is that when you are clicking on the .emoticons and executing your popover function, it is at that moment that you are binding it to your click. That's why it doesn't work the first time, but it works afterwards. It starts listening to the click event after that.
Ideally, the solution is to run the .popover function when the new content is loaded (on your AJAX callback).
If you want to just copy paste my code and see if it works, you can do this:
$('body').on('click','.emoticons',function()
{
// Convert this element into a popover and then display it
$(this).popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {
return $('.emoticonimg').html();
}
}).popover('toggle');
});
But, I would NOT recommend this code specifically, since you are re-initializing your popover every time you click on it.
It's better and more clear if you bind all popovers after your AJAX request is done:
$.ajax( "BlaBlaBla.php" )
.done(function() {
// Convert all emoticons to popovers
$(".emoticons").popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {
return $('.emoticonimg').html();
}
});
});
It doesn't work the first time because the first click if firing off the body onclick handler which binds your popover.
Try something like this in your $(document).ready() function.
$(".emoticons").click(function(){
$(this).popover({
html : true,
placement : 'bottom',
animation : true,
delay: { show: 100, hide: 500 },
content: function() {return $('.emoticonimg').html();
}
});
});

Which wysiwyg editor works fine with fancybox?

I used to work with tinymce, but it causes lot of troubles when I want to put it to fancybox (fails with second start of fancybox window). Cleditor doesn't work too (displays "true" instead of editor). Is there any editor which will work without making any strange tricks?
Edit:
$('.fancybox_with_wysiwyg').fancybox({padding: 1, scrolling: 'no',
beforeShow: function () { tinymce.execCommand('mceToggleEditor', false, 'fbwysiwyg'); },
beforeClose: function () { tinymce.EditorManager.execCommand('mceRemoveControl', true, 'fbwysiwyg'); }
});
Edit2 (fixed callbacks)
$('.fancybox_with_wysiwyg').fancybox({
padding: 1,
scrolling: 'no',
onComplete : function() {
tinyMCE.execCommand('mceToggleEditor', false, 'fbwysiwyg');
},
onCleanup : function() {
tinyMCE.execCommand('mceRemoveControl', false, 'fbwysiwyg' );
}
});
Solution (thanks to Thariama)
$('.fancybox_with_wysiwyg').fancybox({padding: 1, scrolling: 'no',
onComplete: function () { tinymce.execCommand('mceAddControl', false, 'fbwysiwyg'); },
onClosed: function () { tinyMCE.execCommand('mceRemoveControl', false, 'fbwysiwyg' ); }
});
>I used to work with tinymce, but it causes lot of troubles when I want to put
>it to fancybox (fails with second start of fancybox window).
The simple solution for this case is to shut down tinymce correctly before you reinitialize it the second time.
To shut your editor instance down call
tinyMCE.execCommand('mceRemoveControl', false, 'fbwysiwyg' );
Update: You need to use
$('.fancybox_with_wysiwyg').fancybox({padding: 1, scrolling: 'no',
beforeShow: function () { tinymce.execCommand('mceToggleEditor', false, 'fbwysiwyg'); },
beforeClose: function () { tinyMCE.execCommand('mceRemoveControl', false, 'fbwysiwyg' ); }
});
CKEditor definately works as I've been working on putting it inside a Fancybox this afternoon :)
The problem you may encounter is when a modal window plugin removes and recreates the textarea within the modal. In this case you will need to re-bind the WYSIWYG when the textarea is shown.

Categories