How to load vtip tooltip on a dynamically generated element? - jquery-plugins

I'm new to jQuery and trying to combine the use of a tooltip plugin and a lightbox plugin. More specifically, I am using Colorbox and vtip.
Colorbox generates a div which displays an image like this:
<div id="cboxLoadedContent" style="display: block; width: 400px; overflow: auto; height: 498px;">
<br>
<img src="image.jpg" id="cboxPhoto" style="margin: 49px auto auto; border: medium none; display: block; float: none; cursor: pointer;">
<br>
</div>
</code>
I next add class="vtip" title="This is a tip." in order to use the vtip style, but for some reason it does not work when it's a title tag on an element dynamically generated by Colorbox, but works on anything already loaded on the page.
Can anyone explain to me why this is and possibly offer some solutions to fix this problem?

If you don't want to have to re-call the function every time a new element is written to the page, I wrote an update to vtip. I rewrote the vtip function as a jQuery plugin, to be chainable, to allow custom settings, and to work with live elements. Its using a mapping of events, so it will work with jQuery 1.4.3 and up.
(function ($) {
$.fn.vtip = function (options) {
var settings = {
xOffset: -10,
yOffset: 6,
arrow: '/images/vtip_arrow.png'
};
if (options) $.extend(settings, options);
return this.live({
mouseenter: function (a) {
this.t = this.title;
this.title = "";
this.top = (a.pageY + settings.yOffset);
this.left = (a.pageX + settings.xOffset);
$("body").append('<p id="vtip"><img id="vtipArrow" />' + this.t + "</p>");
$("p#vtip #vtipArrow").attr("src", settings.arrow);
$("p#vtip").css("top", this.top + "px").css("left", this.left + "px").fadeIn("fast");
},
mouseleave: function (a) {
this.title = this.t;
$("p#vtip").fadeOut("fast").remove();
},
mousemove: function (a) {
this.top = (a.pageY + settings.yOffset);
this.left = (a.pageX + settings.xOffset);
$("p#vtip").css("top", this.top + "px").css("left", this.left + "px");
}
});
};
})(jQuery);
// You can use it with any class, I'm using the class 'vtip' below.
$(document).ready(function(){
$('.vtip').vtip();
});
// If necessary, add custom settings like so:
$('.vtip').vtip({xOffset:-10,yOffset:10,arrow:'/images/customArrow.png'});

I tried the code/re-written plugin on this page and ran into some complications... perhaps this will work better for someone and save you some time:
(function ($) {
$.fn.vtip = function (options) {
var settings = {
xOffset: -10,
yOffset: 20,
arrow: 'http://simages0.showtimesfast.com/icons2/vtip_arrow.png'
};
if (options) $.extend(settings, options);
return this.live('mouseover mouseout mousemove', function(a){
if(a.type == 'mouseover'){
this.top = (a.pageY + settings.yOffset);
this.left = (a.pageX + settings.xOffset);
$("body").append('<p id="vtip"><img id="vtipArrow" />' + this.title + "</p>");
$("p#vtip #vtipArrow").attr("src", settings.arrow);
$("p#vtip").css("top", this.top + "px").css("left", this.left + "px").fadeIn("fast");
}else if (a.type == 'mouseout'){
$("p#vtip").fadeOut("fast").remove();
}else if (a.type == 'mousemove'){
this.top = (a.pageY + settings.yOffset);
this.left = (a.pageX + settings.xOffset);
$("p#vtip").css("top", this.top + "px").css("left", this.left + "px");
}
});
};
})(jQuery);
Currently in use on http://www.showtimes.ca/ for you to see it working in action. Thanks to Steve above as you led me in the right direction for working with live events.

The clue is at the bottom of the vtip file:
jQuery(document).ready(function($){vtip();})
vtip is being called in document ready. It doesnt know about the elements you havent yet added. You need to recall the vtip function after you've added your elements.
vtip();
PS vtip hasnt been written as a plugin, otherwise you could chain it together with your other code eg
$('div').append('<a>example</a>').vtip(); //currently this wont work
You might want to contact the author and suggest the change, or find another tooltip - there are plenty around.

Related

Print all pages in kendo grid

I'm trying to print all pages of kendo grid
I search alot I used this link
http://docs.telerik.com/KENDO-UI/controls/data-management/grid/walkthrough#printing
to print grid ,but it print the current page.
like this
note linked name still appear as linked and user can press it in print page.
I tried to use this code to load all pages , but it is not work since it show print page then load grid with all page items
var dataSource = gridElement.data("kendoGrid").dataSource;
dataSource.pageSize(dataSource.total());
I want to print all pages of grid in friendly layout , like one export grid to pdf it export friendly grid to print
Edit 1
here is my script to print all grid pages but it not work
$('#printGrid').click(function () {
printGrid();
});
function printGrid() {
var gridElement = $('#PageGrid'),
printableContent = '',
win = window.open('', '', 'width=800, height=500');
var dataSource = gridElement.data("kendoGrid").dataSource;
dataSource.pageSize(dataSource.total());
var htmlStart =
'<!DOCTYPE html>' +
'<html>' +
'<head>' +
'<link href="http://kendo.cdn.telerik.com/' + kendo.version + '/styles/kendo.common.min.css" rel="stylesheet" /> ' +
'<meta charset="utf-8" />' +
'<title>#GlobalResources.Print</title>' +
'<style>' +
'html { font: 11pt sans-serif; }' +
'.k-grid { border-top-width: 0; }' +
'.k-grid, .k-grid-content { height: auto !important; }' +
'.k-grid-content { overflow: visible !important; }' +
'div.k-grid table { table-layout: auto; width: 100% !important; }' +
'.k-grid .k-grid-header th { border-top: 1px solid; }' +
'.k-grid-toolbar, .k-grid-pager > .k-link { display: none; }' +
'</style>' +
'</head>' +
'<body>';
var htmlEnd =
'</body>' +
'</html>';
var gridHeader = gridElement.children('.k-grid-header');
if (gridHeader[0]) {
var thead = gridHeader.find('thead').clone().addClass('k-grid-header');
printableContent = gridElement
.clone()
.children('.k-grid-header').remove()
.end()
.children('.k-grid-content')
.find('table')
.first()
.children('tbody').before(thead)
.end()
.end()
.end()
.end()[0].outerHTML;
} else {
printableContent = gridElement.clone()[0].outerHTML;
}
doc = win.document.open();
doc.write(htmlStart + printableContent + htmlEnd);
doc.close();
win.print();
}
var gridElement = $('#PopUpGrid'),
printableContent = '',
win = window.open('', '', 'width=800, height=500, resizable=1, scrollbars=1'),
doc = win.document.open();
var htmlStart =
'<!DOCTYPE html>' +
'<html>' +
'<head>' +
'<meta charset="utf-8" />' +
'<title>Kendo UI Grid</title>' +
'<link href="http://kendo.cdn.telerik.com/' + kendo.version + '/styles/kendo.common.min.css" rel="stylesheet" /> ' +
'</head>' +
'<body>';
var htmlEnd =
'</body>' +
'</html>';
var gridHeader = gridElement.children('.k-grid-header');
if (gridHeader[0]) {
var thead = gridHeader.find('thead').clone().addClass('k-grid-header');
printableContent = gridElement
.clone()
.children('.k-grid-header').remove()
.end()
.children('.k-grid-content')
.find('table')
.first()
.children('tbody').before(thead)
.end()
.end()
.end()
.end()[0].innerHTML;
} else {
printableContent = gridElement.clone()[0].innerHTML;
}
doc.write(htmlStart + printableContent + htmlEnd);
doc.close();
win.print();
}
I hope you find it usefull. feel free to comment my errors
thanks.
The reason why your code is not working is that you are are setting
var dataSource = gridElement.data("kendoGrid").dataSource; dataSource.pageSize(dataSource.total());
inside your printGrid(). When you call dataSource.pageSize() then grid needs some time to reload records as per new pagesize and therefore your printGrid code doesn't wait for grid dataBound event to get completed. Hence you will only see the current page in your print preview as the grid reload is not completed yet.
So in order to solve this problem. First set datasource page size when user click print button like below:
$('#printGrid').click(function () {
var dataSource = $("#grid").data("kendoGrid").dataSource;
dataSource.pageSize(dataSource.total());
});
Then You need to move the method call printGrid() method to grid's dataBound event with the condition when pagesize equals the total record as below. This condition will confirm that the user has clicked on the print button. As earlier we had set data source pagesize to total record count in printGrid() method:
dataBound: function(e){
var grid = this;
if(grid.dataSource.data().length === grid.dataSource.total())
{
printGrid();
}
},
With this change now printGrid() only get call once grid reload is completed. I have prepared a full working example at dojo :
https://dojo.telerik.com/#vishwas.upadhyay#neuralt.com/uBAMOpuq
Cons
Loading all the records for printing has a serious problems when record size is larger. The browser will take a significant amount of time to load thousands of records or it might be unresponsive. So if your application renders a large number of records then you should be extra careful with this approach.

nvd3 piechart.js - How to edit the tooltip? version 1.8

I have am using piechart by nvd3. Lately I upgraded nvd3 to 1.8.1 and I need to overwrite tooltip. This is my code from older version:
piechartCurrent.tooltip.contentGenerator(function (obj) {
content = '<h3 style="background-color: ';
content += obj.color + '">';
content += obj.data.key + '</h3><p>$' + Math.round(obj.data.y * 100) / 100 + ' ('+ obj.data.symbols +')</p>';
return content;
});
Which looks like this:
But I would like to use new style for tooltip:
What is html code for new tooltip? I need to overwrite tooltip, since I need some custom text there.
Edit:
Jsfiddle example
Edit 2:
Jsfiddle with symbols.
If you are using NVD3 v1.8.1 the tooltip header will hidden by default. But try this :
piechartCurrent.tooltip.headerEnabled(false);
Here is a link to its source
UPDATED ANSWER
You need to remove the chart.tooltip.contentGenerator() function to use the default styles, you have been overriding the default all this time.
There are two parts in the tooltip, if you want to override. The Key and the Value. The Key is where the chart element is displayed, eg: "Finance"
chart.tooltip.keyFormatter(function (d, i) {
var symbol = '';
pieSectorData().forEach(function (entry) {
// Search data for key and return the symbols
if (entry.key == d){
symbol = entry.symbols
}
});
return d + '(' + symbol + ')'
});
And to format your value in the tooltip with the $ symbol use the following :
chart.tooltip.valueFormatter(function (d, i) {
return '$' + d
});
Hope it helps.
For some reason shabeer90's answer did not work for me after all. I was working/changing symbols in js file and that did not take any effect. So I used my original code tooltip.contentGenerator. I simple hardcoded color in there with div:
style.css:
.square-box {
float: left;
width: 10px;
height: 10px;
margin: 4px;
border-width: 1px;
border-style: solid;
border-color: rgba(0,0,0,.2);
}
and js to edit chart's toltip:
chart.tooltip.contentGenerator(function (obj) {
content = '<p><div class="square-box" style="background-color:'+obj.color+';"></div> '+
obj.data.key +' ('+ obj.data.symbols +') <strong>$' + Math.round(obj.data.y * 100) / 100 + '</strong> </p>';
return content;
});

lazy load doesnt work with hidden elements

this is my simple test code for lazy load
http://codepen.io/kevkev/pen/bVVGdE
it works so far .. but the thing is that hidden images in an onclick function for buttons etc. doesnt work!
(watch through my code and scroll to end and push the button)
you can see in the network feedback that it already had load the images.
i could figure out that the problem is "display:none"
.pop {
display:none;
z-index:99;
position:absolute;
width:100%;
height:auto;
background:inherit;
}
Because display: none; elements are unknown in position. And the lazyloader doesn't know, when and if you change this. Therefore it decides to eager load it. If you want a lazyloader that automatically detects this use https://github.com/aFarkas/lazysizes/.
As alternative I would recommend justlazy, because it's more lightweight and don't uses jQuery.
1. Define placeholder (similar to that what you have done):
<span data-src="path/to/image" data-alt="alt" data-title="title"
class="placeholder">
</span>
2. Initialize lazy loading after your button click:
$(document).ready(function () {
$("#art").click(function () {
$("#art_pop").fadeIn(300);
Justlazy.registerLazyLoadByClass("placeholder", {
// image will be loaded if it is 300 pixels
// below the lower display border
threshold: 300
});
});
// other code ..
});
thanks guys! but I also got a working solution on this:
http://codepen.io/kevkev/full/meebpQ/
$(document).ready(function () {
$("#art").click(function () {
$("#art_pop").fadeIn(300);
});
$(".pop > span, .pop").click(function () {
$(".pop").fadeOut(600);
});
});
;(function($) {
$.fn.unveil = function(threshold, callback) {
var $w = $(window),
th = threshold || 0,
retina = window.devicePixelRatio > 1,
attrib = retina? "data-src-retina" : "data-src",
images = this,
loaded;
this.one("unveil", function() {
var source = this.getAttribute(attrib);
source = source || this.getAttribute("data-src");
if (source) {
this.setAttribute("src", source);
if (typeof callback === "function") callback.call(this);
}
});
function unveil() {
var inview = images.filter(function() {
var $e = $(this);
if ($e.is(":hidden")) return;
var wt = $w.scrollTop(),
wb = wt + $w.height(),
et = $e.offset().top,
eb = et + $e.height();
return eb >= wt - th && et <= wb + th;
});
loaded = inview.trigger("unveil");
images = images.not(loaded);
}
$w.on("scroll.unveil resize.unveil lookup.unveil", unveil);
unveil();
return this;
};
})(window.jQuery || window.Zepto);
/* OWN JAVASCRIPT */
$(document).ready(function() {
$("img").unveil(200, function() {
$(this).load(function() {
this.style.opacity = 1;
});
});
});

JCarousel and JqueryUI slider issue

Hi I'm very new to javascript and Jquery. I found the Jcarousel plugin recently and I've tried several of the examples on sorgalla, but can't seem to figure it out.
What i want is to populate the carousel with images(links) from a database, the selection of images i want to display are based on 2 date parameters i get from a jqueryui slider. My idea was to do a ajax request with the "from" and "to" date parameters to a python script which returns the image links in JSON format. But my problem is that when I select a new range of images from the slider the carousel goes bananas(displaying empty boxes or half images).
I would appreciate if someone could nudge me in the right direction here, thanks.
Here's my script:
<script type="text/javascript">
function js(){
$('#mycarousel').empty();
var start_d=$("#valueAA").val();
var end_d=$("#valueBB").val();
$.getJSON("http://www.xxx.com/zzzzzzzzz/cgi-bin/hnf.py" ,
{start_d: start_d, end_d: end_d} ,
function(data){
var encoded = $.toJSON(data);
for(var i=0; i < data.articles.length; i++) {
$('#mycarousel').append('<li><img src="' + $.evalJSON(encoded).articles[i].img + '" width="120" height="100" alt="" /></li>');
}
jQuery('#mycarousel').jcarousel({scroll: 1});
}
);
}
$(document).ready(function() {
$(function(){
$('select#valueAA, select#valueBB').selectToUISlider({
sliderOptions: {
stop: function(e,ui) {
js();
}
}
});
labels: 12
//fix color
fixToolTipColor();
});
//quick function for tooltip color match
function fixToolTipColor(){
//grab the bg color from the tooltip content - set top border of pointer to same
$('.ui-tooltip-pointer-down-inner').each(function(){
var bWidth = $('.ui-tooltip-pointer-down-inner').css('borderTopWidth');
var bColor = $(this).parents('.ui-slider-tooltip').css('backgroundColor')
$(this).css('border-top', bWidth+' solid '+bColor);
});
}
});
</script>
Found a solution:
I can't just empty my ul for some reason, but a fix is to place your ul in a wrapper and destroy that wrapper and remake the ul between each imageset. Probably not the sexiest solution but it works..
solution:
function js(){
$('#wrap').remove();
$('#container').append('<div id ="wrap"></div>');
$('#wrap').append('<ul id="mycarousel" class="jcarousel-skin-tango"></ul>');
var start_d=$("#valueAA").val();
var end_d=$("#valueBB").val();
$.getJSON("http://www.xxx.com/zzz/cgi-bin/hnf.py" ,
{start_d: start_d, end_d: end_d} ,
function(data){
var encoded = $.toJSON(data);
for(var i=0; i < data.articles.length; i++) {
$('#mycarousel').append('<li><img src="' + $.evalJSON(encoded).articles[i].img + '" width="110" height="100" alt="" /></li>');
}
jQuery('#mycarousel').jcarousel({scroll: 1});
}
);
}

AJAX loading indicator

I use this AJAX code:
<script language="javascript" type="text/javascript">
<!--
//Browser Support Code
function ajaxFunction(){
var ajaxRequest; // The variable that makes Ajax possible!
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
// Create a function that will receive data sent from the server
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
var ajaxDisplay = document.getElementById('ajaxDiv');
ajaxDisplay.innerHTML = ajaxRequest.responseText;
}
}
var age = document.getElementById('age').value;
var wpm = document.getElementById('wpm').value;
var sex = document.getElementById('sex').value;
var queryString = "?age=" + age + "&wpm=" + wpm + "&sex=" + sex;
ajaxRequest.open("GET", "file.php" + queryString, true);
ajaxRequest.send(null);
}
//-->
</script>
How to indicate AJAX loading?
Common scenario is to show animated gif image or change mouse cursor on start of ajax request and at end.
Gif is much simpler. Something like (I am using JQuery Syntax):
For start:
$("#progressIndicator").show();
In your onreadystatechange handler
$("#progressIndicator").hide();
If your using JQuery you can do something like this:
$("#progressIndicator").show();
var age = $('#age')[0].value;
var wpm = $('#wpm')[0].value;
var sex = $('#sex')[0].value;
var queryString = "?age=" + age + "&wpm=" + wpm + "&sex=" + sex;
$.get("file.php" + queryString, function (data) {
$("ajaxDiv").html(data);
$("#progressIndicator").hide();
})
you can see more about the JQuery get method
here
You can bind the showing/hiding globally in your app (or just in some part of it) with the following events:
$(document).on({
ajaxStart: function () { $body.addClass("loading"); },
ajaxStop: function () { $body.removeClass("loading"); }
});
And then you define the class loading:
/* Start by setting display:none to make this hidden.
Then we position it in relation to the viewport window
with position:fixed. Width, height, top and left speak
for themselves. Background we set to 80% white with
our animation centered, and no-repeating */
.modal {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, .8 ) url('../Images/Loader.gif') 50% 50% no-repeat;
}
/* When the body has the loading class, we turn the scrollbar off with overflow:hidden */
body.loading {
overflow: hidden;
}
/* Anytime the body has the loading class, our modal element will be visible */
body.loading .modal {
display: block;
}
In this way you don't need to manage the loading effect for every ajax call and you can maintain a consistent style through the entire application.

Resources