Multiple qTip2 on the same element - qtip2

Calling .qtip twice on the same element erases the previous qtip. Is it possible to have 2 styles of qtip on the same element (one is right click, one is mouse over)

You cant have 2 on the same element but you can wrap the element in a span and call qtip on that with a different trigger.

I just upvoted Bruian's answer as I have tried the other technique that I found through Googling which says to create a qtip and to add removeData('qtip') before adding another one :
$('.selector')
.qtip() // tooltip 1
.removeData('qtip') // remove it's data
.qtip(); // tooltip 2
This technique will work for simple cases, but you are setting yourself up for a lot of problems down the line with duplicate ids and other issues.

For those still interested using one description for multiple item. You can use this method:
1) Make one div with all the description item you want.for example:
<div id='description' class='describe_content' style='display:none;'>
<div id='test'>this is description</div>
<div id='test2'>teeest</div>
</div>
2) Use the following code for the qtip. You can see the comment on what each item do.
$(document).on('mouseover','input ,select ,dl , .dropdown2 .mutliSelect li',function(event)
{
string = $("#test2");
$(this).qtip({
overwrite: true, //to allow it the same item be paste to other part.
position: {
my: pos[pos_c+3], // Position my top left...
at: pos[pos_c], // at the bottom right of...
target: $(this) // my target
},
content: {
text: string, // the text
},
show:{
event: event.type, //use the same show event as the one that triggered
ready: true //show the tooltip as soon as it's bound.
},
'font-size': 16
},event);// have to pass event as second parameter, because qtips positioning
}
Note that the position is just a extra option, you could remove it if you want.

Related

Focus, blur, focusin, focusout, don't work with D3 and SVG Elements? Is there an alternative?

I'm using the d3 library to create a widget within a SVG. Within the SVG I'm trying to do the following:
There are small rectangles that are clickable. Once clickable, they should "enlarge" and show some input fields. When I click outside the rectangles I want them to "un-enlarge" and remove the input fields again.
Small rectangle:
Once clicked, they enlarge (no input fields yet):
When I click outside of the white rectangle, I want it to revert back to picture 1:
I trigger the enlargement with an on click event:
let whiteRect = node.append("g")
.on('click', function(a) {
// Trigger enlarge function
return a;
})};
And I would like to trigger the "click outside" using a blur or focusout event. But this doesn't seem to work for SVG. Something like this:
let whiteRect = node.append("g")
.on('blur', function(a) {
// Trigger "un-enlarge" function
return a;
})};
I've been doing some searching, and it seems that in SVG 2 this might be supported, but this doesn't seem to be implemented by any browsers.
Anyone have an idea how I could implement this? I know I can add an onclick event listener for the whole SVG and write some logic there to identify if I'm clicking on an enlarged rectangle. But I'd prefer using something easier like blur or focusout if possible. Any ideas?
Shortly after posting I found this tutorial on focusing svg elements: https://allyjs.io/tutorials/focusing-in-svg.html
Turns out if you add a focus event to an element it becomes focusable and also gets a blur event. So what I did was add an empty focus event to be able to use the blur.
let whiteRect = node.append("g")
.on('click', function(a) {
// Trigger enlarge function
return a;
})}
.on('focus', function(a) {
// Empty focus event
return a;
})}
.on('blur', function(a) {
// Trigger un-enlarge function
return a;
})};
Which worked for me.

Typed.js initialize with existing text and then loop it

I'm working with typed.js to get some words typed. I would like the first word to be showing when the page loads and start the loop from there. In order to get this result I've just placed "nice" in between the span tags, did this the trick.
But... When looking to the following codepen, you can see that the first loop is correct. When the second loop starts, the first word (nice) is not being typed but just appears and disappears quickly. I could really use some help to fix this. Any thoughts?
var typewriter = $('.typewriter');
if(typewriter.length) {
function initTypewriter() {
var typed = new Typed(".typewriter", {
strings: $(".typewriter").attr("data-typewriter").split("|").map(function(e) {
return e
}),
typeSpeed: 80,
backSpeed: 75,
startDelay: 1000,
backDelay: 2000,
loop: !0,
loopcount: false,
showCursor: false,
callback: function(e){ } // call function after typing is done
});
};
initTypewriter();
};
<h2>A <span title="nice, clean, good" class="typewriter" data-typewriter="nice|clean|good">nice</span> example</h2>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/typed.js/2.0.6/typed.min.js"></script>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
CodePen Link
Kind regards
I realise this question is over 2 years old now, but I came across this issue today and couldn't find a solution either so put together a workaround.
Essentially, create 2 instances of Typed JS.
The first removes the existing text and uses the onComplete method to remove itself, clear the text content from the DOM and then setup the second instance to do the actual loop.
My example has no dependencies outside of Typed JS, but you could adapt to jQuery selectors, etc, pretty easily.
Demo here: https://codepen.io/jneale/pen/pogyzXK
HTML
<h1>Hello <span class="typed-replaced">world</span></h1>
Javascript
function setupTypedReplace() {
// the text node to type in
var typed_class = 'typed-replaced';
// the original text content to replace, but also use
var replace_text = 'world';
var options = {
strings: ['there', 'buddy', replace_text], // existing text goes at the end
typeSpeed: 80,
backSpeed: 60,
backDelay: 1000,
loop: true,
smartBackspace: false,
cursorChar: '_',
attr: null
};
// clear out the existing text gracefully then setup the loop
new Typed('.' + typed_class, {
strings: [replace_text, ''],
backSpeed: options.backSpeed,
backDelay: options.backDelay,
cursorChar: options.cursorChar,
attr: options.attr,
startDelay: 700,
onComplete: function (t) {
// existing text has now been removed so let's actually clear everything out
// and setup the proper Typed loop we want. If we don't do this, the original
// text content breaks the flow of the loop.
t.destroy();
document.getElementsByClassName(typed_class)[0].textContent = '';
new Typed('.' + typed_class, options);
}
});
}
setupTypedReplace();

Paste as plain text Contenteditable div & textarea (word/excel...)

I would like the to paste text in a contenteditable div, but reacting as a textarea.
Note that I want to keep the formatting as I would paste it in my textarea (from word, excel...).
So.
1) Paste text in contenteditable div
2) I get the text from clipboard
3) I push my value from clipboard to my textarea, (dont know how??)
4) Get value from my textarea and place it in my contenteditable div
Any suggestions?
I'm CKEditor's core developer and by coincidence for last 4 months I was working on clipboard support and related stuff :) Unfortunately I won't be able to describe you the entire way how pasting is handled, because the tales of the impl are too tricky for me even after writing impl by myself :D
However, here're some hints that may help you:
Don't write wysiwyg editor - use one that exists. It's going to consume all your time and still your editor will be buggy. We and guys from other... two main editors (guess why only three exist) are working on this for years and we still have full bugs lists ;).
If you really need to write your own editor check out http://dev.ckeditor.com/browser/CKEditor/trunk/_source/plugins/clipboard/plugin.js - it's the old impl, before I rewrote it, but it works everywhere where it's possible. The code is horrible... but it may help you.
You won't be possible to handle all browsers by just one event paste. To handle all ways of pasting we're using both - beforepaste and paste.
There's number (huge number :D) of browsers' quirks that you'll need to handle. I can't to describe you them, because even after few weeks I don't remember all of them. However, small excerpt from our docs may be useful for you:
Paste command (used by non-native paste - e.g. from our toolbar)
* fire 'paste' on editable ('beforepaste' for IE)
* !canceled && execCommand 'paste'
* !success && fire 'pasteDialog' on editor
Paste from native context menu & menubar
(Fx & Webkits are handled in 'paste' default listner.
Opera cannot be handled at all because it doesn't fire any events
Special treatment is needed for IE, for which is this part of doc)
* listen 'onpaste'
* cancel native event
* fire 'beforePaste' on editor
* !canceled && getClipboardDataByPastebin
* execIECommand( 'paste' ) -> this fires another 'paste' event, so cancel it
* fire 'paste' on editor
* !canceled && fire 'afterPaste' on editor
The rest of the trick - On IEs we listen for both paste events, on the rest only for paste. We need to prevent some events on IE, because since we're listening for both sometimes this may cause doubled handling. This is the trickiest part I guess.
Note that I want to keep the formatting as I would paste it in my textarea (from word, excel...).
Which parts of formatting do you want to keep? Textarea will keep only basic ones - blocks formatting.
See http://dev.ckeditor.com/browser/CKEditor/trunk/_source/plugins/wysiwygarea/plugin.js#L120 up to line 123 - this is the last part of the task - inserting content into selection.
Current solution works perfect in IE/SAF/FF
But still i need a fix for "non" keyboard events, when pasting with mouse click...
Current solution for keyboard "paste" events:
$(document).ready(function() {
bind_paste_textarea();
});
function bind_paste_textarea(){
var activeOnPaste = null;
$("#mypastediv").keydown(function(e){
var code = e.which || e.keyCode;
if((code == 86)){
activeOnPaste = $(this);
$("#mytextarea").val("").focus();
}
});
$("#mytextarea").keyup(function(){
if(activeOnPaste != null){
$(activeOnPaste).focus();
activeOnPaste = null;
}
});
}
<h2>DIV</h2>
<div id="mypastediv" contenteditable="true" style="width: 400px; height: 400px; border: 1px solid orange;">
</div>
<h2>TEXTAREA</h2>
<textarea id="mytextarea" style="width: 400px; height: 400px; border: 1px solid red;"></textarea>
I have achieved this using rangy library to save and restore selections.
I also perform some other work using the library in the same functions, which I have stripped out of this example, so this is not optimal code.
HTML
<div><div id="editor"contenteditable="true" type="text"></div><div>
Javascript
var inputArea = $element.find('#editor');
var debounceInterval = 200;
function highlightExcessCharacters() {
// Bookmark selection so we can restore it later
var sel = rangy.getSelection();
var savedSel = sel.saveCharacterRanges(editor);
// Strip HTML
// Prevent images etc being pasted into textbox
inputArea.text(inputArea[0].innerText);
// Restore the selection
sel.restoreCharacterRanges(editor, savedSel);
}
// Event to handle checking of text changes
var handleEditorChangeEvent = (function () {
var timer;
// Function to run after timer passed
function debouncer() {
if (timer) {
timer = null;
}
highlightExcessCharacters();
}
return function () {
if (timer) {
$timeout.cancel(timer);
}
// Pass the text area we want monitored for exess characters into debouncer here
timer = $timeout(debouncer, debounceInterval);
};
})();
function listen(target, eventName, listener) {
if (target.addEventListener) {
target.addEventListener(eventName, listener, false);
} else if (target.attachEvent) {
target.attachEvent("on" + eventName, listener);
}
}
// Start up library which allows saving of text selections
// This is useful for when you are doing anything that might destroy the original selection
rangy.init();
var editor = inputArea[0];
// Set up debounced event handlers
var editEvents = ["input", "keydown", "keypress", "keyup", "cut", "copy", "paste"];
for (var i = 0, eventName; eventName = editEvents[i++];) {
listen(editor, eventName, handleEditorChangeEvent);
}

qtip2 close button without a title bar

I would like to have a qtip2 tooltip without a title bar, but with a close icon in the corner. Is there a way to spec that, or do I have to muck with the code that creates it? I am thinking of something that floats the button to the left or to the right, allowing the rest of the content to fill the tooltip div.
Always keep the close markup separately and update with your current qTip Text.
$('.selector').qtip({
content: {
text: function(api) {
var qTipContent = $('.close-markup').html();
qTipContent += $('.qtip-content').html();
return $('.qtip-content').html();
}
}
});
$('.close-markup').qtip('destroy');
Try the above code.
Note: Does not require to muck the qTip Close code snippet!

jqGrid - Change filter/search pop up form - to be flat on page - not a dialog

I am using jqgrid.
I really need help with this, and have no clue how to do it, but i am sure its possible... can any one give me even a partial answer? were to start from?
I now have a requirement saying that for searching and filtering the grid I dont want the regular model form pop op thing opening, instead the filter should be open when entering the page but not as a pop up form , but should be on the top of the page but still have all the functions to it.
Needs to look like this:
And again having the select tag filled with the correct information (like they do in the popup form) and when clicking on "Save" it should send the request to the server, like regular.
Is this possible?
*******EDIT*******
The only thing i basically need is to have the filter with out the dialog part of it.
The solution of the problem for the old searching dialog you can find here. I modified the demo to the current implementation of the searching dialog in the jqGrid.
You can see the results on the demo:
The corresponding code is below:
var $grid = $('#list');
// create the grid
$grid.jqGrid({
// jqGrid opetions
});
// set searching deafauls
$.extend($.jgrid.search, {multipleSearch: true, multipleGroup: true, overlay: 0});
// during creating nevigator bar (optional) one don't need include searching button
$grid.jqGrid('navGrid', '#pager', {add: false, edit: false, del: false, search: false});
// create the searching dialog
$grid.jqGrid('searchGrid');
var gridSelector = $.jgrid.jqID($grid[0].id), // 'list'
$searchDialog = $("#searchmodfbox_" + gridSelector),
$gbox = $("#gbox_" + gridSelector);
// hide 'close' button of the searchring dialog
$searchDialog.find("a.ui-jqdialog-titlebar-close").hide();
// place the searching dialog above the grid
$searchDialog.insertBefore($gbox);
$searchDialog.css({position: "relative", zIndex: "auto", float: "left"})
$gbox.css({clear:"left"});
Here's the way I implemented it, using Oleg's excellent help.
I wanted my users to be able to immediately type in a search criteria (in this case, a user's name) and for the jqGrid to show the results. No messing around with the popup Search dialog.
Here's my end result:
To do this, I needed this HTML:
Employee name:
<input type="text" name="employeeName" id="employeeName" style="width:250px" />
<!-- This will be my jqGrid control and pager -->
<table id="tblEmployees"></table>
<div id="pager"></div>
and this JavaScript:
$("#employeeName").on('change keyup paste', function () {
SearchByEmployeeName();
});
function SearchByEmployeeName()
{
// Fetch the text from our <input> control
var searchString = $("#employeeName").val();
// Prepare to pass a new search filter to our jqGrid
var f = { groupOp: "AND", rules: [] };
// Remember to change the following line to reflect the jqGrid column you want to search for your string in
// In this example, I'm searching through the UserName column.
f.rules.push({ field: "UserName", op: "cn", data: searchString });
var grid = $('#tblEmployees');
grid[0].p.search = f.rules.length > 0;
$.extend(grid[0].p.postData, { filters: JSON.stringify(f) });
grid.trigger("reloadGrid", [{ page: 1 }]);
}
Again, my thanks to Oleg for showing how to use these search filters.
It really makes jqGrid much more user-friendly.

Resources