"Tooltip" jQuery plugin breaks - javascript

I'm working on a very light "tooltip" jQuery plugin. Bellow is the code:
(function( $ ) {
$.fn.tooltip = function() {
return this.each(function(){
var target = $(this);
target.on("mouseover", function(event){
var tooltip = $(document.createElement("div"));
tooltip
.html(target.attr("tooltip-text"))
.addClass("tooltip")
.css({
"top" : event.pageY,
"left":event.pageX
})
.fadeIn(300);
});
});
};
})( jQuery );
And I apply it like so:
<script>
$("div.product").tooltip();
</script>
The idea is to have the tooltip appear when the user hovers the DIV, next to the cursor.
However, when I hover such a DIV (class "product"), the script crashes at the .addClass("tooltip") line:
Uncaught TypeError: Object has no method 'addClass'
What is it that I'm doing wrong?

It's because you're assigning the attribute tooltip-text:
.html(target.attr("tooltip-text"))
The attribute is undefined, so it screws up the chaining of your jQuery events. Try doing this:
.html(target.attr("tooltip-text") || "")
You also don't need to stick the execution in window.onload, putting it in a standard document ready will work fine.

Do not know why but use
.attr("style", tooltip.attr("style") + " tooltip")
instead of .addClass.
Hope this helps.

Related

jQuery slideDown not working on element with dynamically assigned id

EDIT: I cleaned up the code a bit and narrowed down the problem.
So I'm working on a Wordpress site, and I'm trying to incorporate drop-downs into my menu on mobile, which means I have to use jQuery to assign classes and id's to my already existing elements. I have this code that already works on premade HTML, but fails on dynamically created id's.
Here is the code:
...
var menuCount = 0;
var contentCount = 0;
//find the mobile menu items
var submenus = $('[title="submenu"]');
if (submenus.length && submenus.parent('.fusion-mobile-nav-item')) {
console.log(submenus);
submenus.addClass('dropdown-title').append('<i id="dropdown-angle" class="fa fa-angle-down" aria-hidden="true"></i>');
submenus.each(function() {
$(this).attr("href", "#m" + menuCount++);
})
var content = submenus.parent().find('ul.sub-menu');
content.addClass('dropdown-content');
content.each(function() {
$(this).attr("id", "m" + contentCount++);
})
}
$(document).on('click', '.dropdown-title', function(e) {
var currentAttrValue = $(this).attr('href');
if ($(e.target).is('.d-active') || $(e.target).parent('.dropdown-title').is('.d-active')) {
$(this).removeClass('d-active');
$(currentAttrValue).slideUp(300).removeClass('d-open');
} else {
$('.dropdown-title').removeClass('d-active');
$('.dropdown-content').slideUp(300).removeClass('d-open');
$(this).addClass('d-active');
console.log($(currentAttrValue));
//THIS LINE FAILS
$(currentAttrValue).slideDown(300).addClass('d-open');
}
e.preventDefault();
});
I've registered the elements with the class dropdown-title using $(document).on(...) but I can't figure out what I need to do to register the elements with the custom ID's. I've tried putting the event callback inside the .each functions, I've tried making custom events to trigger, but none of them will get the 2nd to last line of code to trigger. There's no errors in the console, and when I console log the selector I get this:
[ul#m0.sub-menu.dropdown-content, context: document, selector: "#m0"]
0
:
ul#m0.sub-menu.dropdown-content
context
:
document
length
:
1
selector
:
"#m0"
proto
:
Object[0]
So jQuery knows the element is there, I just can't figure out how to register it...or maybe it's something I'm not thinking of, I don't know.
If you are creating your elements dynamically, you should be assigning the .on 'click' after creating those elements. Just declare the 'on click' callback code you posted after adding the ids and classes instead of when the page loads, so it gets attached to the elements with .dropdown-title class.
Check this jsFiddle: https://jsfiddle.net/6zayouxc/
EDIT: Your edited JS code works... There also might be some problem with your HTML or CSS, are you hiding your submenus? Make sure you are not making them transparent.
You're trying to call a function for a attribute, instead of the element. You probably want $(this).slideDown(300).addClass('d-active'); (also then you don't need $(this).addClass('d-active'); before)
Inside submenus.each loop add your callback listener.
As you are adding the class dropdown-title dynamically, it was not available at dom loading time, that is why event listener was not attached with those elemnts.
var menuCount = 0;
var contentCount = 0;
//find the mobile menu items
var submenus = $('[title="submenu"]');
if (submenus.length && submenus.parent('.fusion-mobile-nav-item')) {
console.log(submenus);
submenus.addClass('dropdown-title').append('<i id="dropdown-angle" class="fa fa-angle-down" aria-hidden="true"></i>');
submenus.each(function() {
$(this).attr("href", "#m" + menuCount++);
// add callback here
$(this).click( function(e) {
var currentAttrValue = $(this).attr('href');
if ($(e.target).is('.d-active') || $(e.target).parent('.dropdown-title').is('.d-active')) {
$(this).removeClass('d-active');
$(currentAttrValue).slideUp(300).removeClass('d-open');
} else {
$('.dropdown-title').removeClass('d-active');
$('.dropdown-content').slideUp(300).removeClass('d-open');
$(this).addClass('d-active');
console.log($(currentAttrValue));
$(currentAttrValue).slideDown(300).addClass('d-active');
}
e.preventDefault();
});
})
var content = submenus.parent().find('ul.sub-menu');
content.addClass('dropdown-content');
content.each(function() {
$(this).attr("id", "m" + contentCount++);
})
}
Turns out my problem is that jQuery is adding to both the mobile menu and the desktop menu, where the desktop menu is being loaded first when I search for that ID that's the one that jQuery finds. So it turns out I was completely wrong about my suspicions.

Targetting and Changing HTML content using jQuery

I'm trying to change the "10" in the HTML below using jQuery:
<div id="ingredients">
<h2>Ingredients</h2>
<h4>Sugar: <span class="sugar">10</span></h4>
Here have been the iterations that I've gone through that have been unsuccessful:
$(document).ready(function() {
$('#ingredients.sugar').html("5");
});
and
$(document).ready(function() {
$('span[class=sugar]').html("5");
});
In addition, how would I store the value of "10" in a variable? I'm trying to do this:
var $sugar = $('#ingredients.sugar').html();
Would that work?
Thanks!
Henry
Try:
$(document).ready(function() {
$('#ingredients .sugar').html("5");
});
Notice the space between; this says look for a .sugar child from the #ingredients parent. You should also be able to do:
var val = $('#ingredients .sugar').html();
You have missed space in your selector, this will work:
$('#ingredients .sugar').html("5");
Here's a version with a simplified selector (don't need #ingredients), factory caching and update without using quotes (5 works fine).
// Document ready
$(function () {
var $sugar = $( '.sugar' ), // Cache jQuery factory
originalValue = $sugar.html(); // Cache original value
// Update value
$sugar.html( 5 );
});

How to set position for dialog created via JavaScript

HTML:
Link
JavaScript
$(document).ready(function() {
$(document.body).on('click',"a",function(event){
if ($(this).hasClass('ui-dialog-titlebar-close')) return;
event.preventDefault();
var data = '<div id="dialog" title="Basic dialog">';
data += '<p>Hello.</p></div>';
$(data).dialog();
});
});
I want to set a position for this dialog. I've tried changing $(data).dialog(); to $(data).dialog('option', 'position', [200,300]);, but it doesn't work. How can I set it?
jsFiddle: http://jsfiddle.net/fcTcf/
it should be:
$(data).dialog({
position: [200, 300]
});
The syntax $(data).dialog('option', 'option-name', value) is used for changing an option of a dialog that has already been initialized. But if you want to specify options at initialization time, you do so using a option object as the argument to the widget.
There is a link to api documentation for the jQuery Dialog Widget and this jQuery position will help you if you want more granular control of the position.
You're using the selector incorrectly.
$(data) where $data is not a class or id, data is a string containing html.
Try $("#dialog").dialog(); And then you surely would be able to figure it out with the API-documentation.
$(document).ready(function() {
$(document.body).on('click',"a",function(event){
if ($(this).hasClass('ui-dialog-titlebar-close')) return;
event.preventDefault();
var data = '<div id="dialog" title="Basic dialog">';
data += '<p>Hello.</p></div>';
var options={
position:[200,300]
};
$(data).dialog(options);
});
});
You can set 'option' like this

execCommand insertHtml, outer div not inserted why?

Why is the DIV not inserted but only the IMG ?
$(document).ready(function() {
$(document).on('click', '#insertImage', function(){
/*
Why is the DIV not inserted ?
*/
var item = "<div class='resizable'><img src='http://www.rockiesventureclub.org/wp-content/uploads/2013/02/flower-icon.png'></div>";
document.execCommand('insertHTML', false,item);
})
});
see:
http://jsfiddle.net/daslicht/gU2jP/#base
Why not doing it with jQuery since you already use it??
http://jsfiddle.net/gU2jP/5/
var _$div = $('<div>'),
_$img = $("<img class='resizeable' id='myImg' src='http://imperavi.com/img/library.jpg' />");
_$div.append(_$img);
$('body').append(_$div);
The background of the Question was the following:
I just like to be able to make the added Image Float Left or Right.
Since jQueryUI automatically adds a wrapper-div around each resizeable item I thought that I need to add it somehow manually in order to assign a id to it.
doug65536 on Freenode helped me to create this solution without the need to create an additionally div manually:
We also discovered that the Fiddle wont work properly in safari
$(document).on('click', '#insertImage', function () {
document.execCommand('insertHTML', false,
"<img class='resizeable' id='myImg' src='http://imperavi.com/img/library.jpg'>");
$(".resizeable").resizable({
aspectRatio: true
}); //just a try here
$('#myImg').parent().css({
'float':'left',
'margin':'15px'
});
})
http://jsfiddle.net/daslicht/6cGbQ/
Thank you very Much !

how to get outerHTML with jquery in order to have it cross-browser

I found a response in a jquery forum and they made a function to do this but the result is not the same.
Here is an example that I created for an image button:
var buttonField = $('<input type="image" />');
buttonField.attr('id', 'butonFshi' + lastsel);
buttonField.val('Fshi');
buttonField.attr('src', 'images/square-icon.png');
if (disabled)
buttonField.attr("disabled", "disabled");
buttonField.val('Fshi');
if (onblur !== undefined)
buttonField.focusout(function () { onblur(); });
buttonField.mouseover(function () { ndryshoImazhin(1, lastsel.toString()); });
buttonField.mouseout(function () { ndryshoImazhin(0, lastsel.toString()); });
buttonField.click(function () { fshiClicked(lastsel.toString()); });
And I have this situation:
buttonField[0].outerHTML = `<INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image jQuery15205073038169030395="44">`
instead the outer function I found gives buttonField.outer() = <INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image>
The function is:
$.fn.outer = function(val){
if(val){
$(val).insertBefore(this);
$(this).remove();
}
else{ return $("<div>").append($(this).clone()).html(); }
}
so like this I loose the handlers that I inserted.
Is there anyway to get the outerHTML with jquery in order to have it cross-browser without loosing the handlers ?!
You don't need convert it to text first (which is what disconnects it from the handlers, only DOM nodes and other specific JavaScript objects can have events). Just insert the newly created/modified node directly, e.g.
$('#old-button').after(buttonField).remove();`
after returns the previous jQuery collection so the remove gets rid of the existing element, not the new one.
Try this one:
var html_text = `<INPUT id=butonFshi1 value=Fshi src="images/square-icon.png" type=image jQuery15205073038169030395="44">`
buttonField[0].html(html_text);
:)
Check out the jQuery plugin from https://github.com/darlesson/jquery-outerhtml. With this jQuery plugin you can get the outerHTML from the first matched element, replace a set of elements and manipulate the result in a callback function.
Consider the following HTML:
<span>My example</span>
Consider the following call:
var span = $("span").outerHTML();
The variable span is equal <span>My example</span>.
In the link above you can find more example in how to use .outerHTML() plug-in.
This should work fine:
var outer = buttonField.parent().html();

Categories

Resources