IE 9+ JQuery drag & drop for div not working - javascript

function OnDragStartElement(e) {
//this.style.opacity = '0.4';
srcElementParent = this;
e.dataTransfer.effectAllowed = 'move';
var elementCount = formElements.length > 0 ? Math.max.apply(Math, formElements.map(function (o) { return o.ID; })) : 0;
var elementText = $(this).children()[0].innerHTML;
var elementType = $($(this).children()[1])[0].value;
var elementID = (elementCount + 1);
var draggedElement = elementText + ': ' + elementText + elementID
//debugger;
e.dataTransfer.setData("dragedElement", draggedElement);
e.dataTransfer.setData('draggedElementType', elementType);
e.dataTransfer.setData('draggedElementID', elementID);
isElementNotPlaced = true;
isdragDivElement = false;
}
An error is thrown:
Unexpected call to method or property access.
The error I see is on the line:
e.dataTransfer.setData("dragedElement", draggedElement);
The same code works fine on Chrome & Firefox.
Does anyone have a solution for this?

Refere this link.
Drag & Drop HTML 5 jQuery: e.dataTransfer.setData() with JSON
no need to set data for each
e.dataTransfer.setData("dragedElement", draggedElement);
e.dataTransfer.setData('draggedElementType', elementType);
e.dataTransfer.setData('draggedElementID', elementID);
instead of this we can pass single json object as text.

Related

dxTooltip not working in IE, working in Chrome

I have got a dxChart:
var chart = $("#chartContainer4").dxChart();
of which I’m taking the legend rectangles:
var PayerLegendBoxes = $("#chartContainer4 .dxc-legend g rect");
And using dxTooltip for showing on mouse hover.
PayerLegendBoxes.each(function () {
var nextElementHTML = this.nextSibling.innerHTML;
var currElementTip = nextElementHTML + "tip";
var currElement = this;
var title = chart.append("<span style='display:none;' id=" + currElementTip + ">" + nextElementHTML + "</span>");
var tooltipSimple = $("#" + currElementTip).dxTooltip({
target: currElement,
}).dxTooltip("instance");
$(currElement).unbind().hover(function () {
tooltipSimple.toggle()
});
});
This is working fine in Chrome but not in IE.
Is there a bug for cross browser functionality?
Looks like the problem is in this line:
var nextElementHTML = this.nextSibling.innerHTML;
nextSibling.innerHTML returns undefined in IE. So, I suggest you use something like this:
// jQuery provides a "cross-browser" way here
var nextElementHTML = $(this).next().text();
And one more correction for this line:
var currElementTip = nextElementHTML + "tip";
nextElementHTML can sometimes contain a white space symbol. So, you should sanitize it:
var currElementTip = (nextElementHTML + "tip").replace(/\s/g, "_");
The updated sample is here - http://jsfiddle.net/5y8f4zt0/

jquery type error :"TypeError: colorval is undefined,"

Here is console screenshort
Plunker Link Here
var color = '';
var xml = '';
function hexc(colorval) {
var parts = $(colorval).match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
delete(parts[0]);
for (var i = 1; i <= 3; ++i) {
parts[i] = parseInt(parts[i]).toString(16);
if (parts[i].length == 1) parts[i] = '0' + parts[i];
}
color = '#' + parts.join('');
}
$("#mcor tr").each(function() {
// alert("1");
xml += '<mcor_info>';
var td_len = $("#mcor tr td").length;
// alert("2");
for (var b = 0; b <= td_len; b++) {
// var index = $('th').eq(b).text();
xml += '<mcor' + b + '>';
var tx = $("#mcor tr ").find("td").eq(b).css('backgroundColor');
hexc(tx);
xml += color;
xml += '</mcor' + b + '>';
}
xml += '</mcor_info>';
});
I am getting this error: Type Error: colorval is undefined.
I found a couple of other examples, tried to solve my error but didn't succeed:
JQuery Type-error e is undefined issue
Uncaught TypeError: undefined is not a function while using jQuery UI
Where is my mistake?
can you upload the code in jsfiddle, please? I suspect that the problem could be on the line "var tx = $("#mcor tr ").find("td").eq(b).css('backgroundColor');"
probably it is not getting the result that you think
UPDATE
what happen if you use that:
var parts = colorval.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
UPDATE #2
you can check the code in the following link:
https://plnkr.co/edit/g3boR5yHO895fz76EIKg
like you can see if I pass a rgb directly to the function it is working fine, that mean that the problem is the "tx" object, that means that you need convert that to string
hexc(String(tx));

Adding onclick event in JavaScript with parameters

I'm trying to make a dropdown to display the results of a request given what the user writes in a field.
The problem I'm encountering is that when I try to add an onclick event to each item in the dropdown, only the last one acts like expected.
The dropdown is a section and I try to include sections in it.
Here is the dropdown :
<section id="projectDrop">
</section>
Here is the code :
var j = 0;
var tmp;
for (var i=0;((i<infos.projects.length) && (i<5));i++)
{
if (infos.projects[i].name.toLowerCase().match(projectName.value.toLowerCase()))
{
projectDrop.innerHTML += '<section id="project' + j + '">' + infos.projects[i].name + '</section>';
tmp = document.getElementById('project' + j);
projectDrop.style.height = (j+1)*20 + 'px';
tmp.style.top = j*20 + 'px';
tmp.style.height = '20 px';
tmp.style.width = '100%';
tmp.style.color = 'rgb(0, 0, 145)';
tmp.style.textAlign = 'center';
tmp.style.cursor = 'pointer';
tmp.style.zIndex = 5;
tmp.onclick = function(name, key)
{
return function()
{
return insertProject(name, key);
};
} (infos.projects[i].name, infos.projects[i].key);
++j;
}
}
The result is visually as I expected, I can see the dropdown with all my projects listed and a pointer while hovering etc...
But only the last project is clickable and trigger the "insertProject" function while the other do nothing.
If someone could help me solve that !
You need to store the key somewhere. Take a look at the solution below, I have used the data-key attribute on the <section> to store the key.
Also note how I have changed the code to create the element object and assign its properties, instead of building a raw string of HTML. The problem with building HTML as a string is you have to worry about escaping quotes, whereas this way you don't.
var j = 0;
var tmp;
for (var i=0;((i<infos.projects.length) && (i<5));i++)
{
if (infos.projects[i].name.toLowerCase().match(projectName.value.toLowerCase()))
{
tmp = document.createElement('section');
tmp.id = "project" + j;
tmp.setAttribute('data-key', infos.projects[i].key);
tmp.innerHTML = infos.projects[i].name;
projectDrop.style.height = (j+1)*20 + 'px';
tmp.style.top = j*20 + 'px';
tmp.style.height = '20 px';
tmp.style.width = '100%';
tmp.style.color = 'rgb(0, 0, 145)';
tmp.style.textAlign = 'center';
tmp.style.cursor = 'pointer';
tmp.style.zIndex = 5;
tmp.onclick = function(){
insertProject(this.innerHTML, this.getAttribute('data-key'));
};
projectDrop.appendChild(tmp);
++j;
}
}
Change:
tmp.onclick = function(name, key)
{
return function()
{
return insertProject(name, key);
};
} (infos.projects[i].name, infos.projects[i].key);
to
tmp.onclick = function(j){
return function(name, key)
{
return function()
{
return insertProject(name, key);
};
} (infos.projects[j].name, infos.projects[j].key);
}(i)

TinyMCE problem with second show. Help

Added tinyMCE as inline editor. Have a next probllem : first time this is work good - show with custom style (as I setup), works correctly but when I click cancel and then start edit again I have empty editor - without text in edit area. so this is a code:
UPD : cm.Node - wrapper for docuement.createElement and el.setAttribute, cm.getByAttr('attr', 'attr_val', el) - get elemnt by attr from el. req - wrapper for AJAX, cm.merge - like array_merge in PHP
var EditBlock = function(){
var my = this;
var o = cm.merge({
'id' : '',
'act' : '',
'val' : '',
'nobr' : false,
'text' : false,
'onSaved' : function(){},
'onSave' : function(){},
'params' : {'iconsPath' : 'interface/common/images/stdc/nicEditorIcons.gif'}
}, arguments[0]);
var prefix = 'tinyMCE_' + Math.random() + '_';
var node = cm.getEl(o.id);
var txtArea = cm.addClass(cm.Node('textarea', {'id' : prefix + o.id, 'style': ('width:' + node.offsetWidth + 'px')}), prefix + o.id);
var saveBtn = cm.Node('input', {'type':'button', 'value':'Save'});
var cancelBtn = cm.Node('input', {'type':'button', 'value':'Cancel'});
var container = cm.Node('div', txtArea, cm.Node('div', saveBtn, cancelBtn));
var plainText = function(node){
var str = '';
var childs = node.childNodes;
for(var i = 0, ln = childs.length; i < ln; i++){
if(childs[i].nodeType == 3)
str += childs[i].nodeValue;
else if(childs[i].childNodes.length)
str += plainText(childs[i]);
}
return str;
}
var init = function(){
node.onclick = my.edit;
cancelBtn.onclick = my.close;
saveBtn.onclick = function(){
my.save();
my.close();
}
}
my.save = function(){
var tmp = cm.Node('div', tinyMCE.get(prefix + o.id).getContent());
var content = o.text? plainText(tmp) : tmp.innerHTML;
o.onSave(content);
node.innerHTML = content;
req({
'act' : o.act,
'data' : 'data[content]=' + escape(content) + (o.val? '&data[val]=' + o.val : ''), 'handler' : function(){o.onSaved(content)}
});
}
my.close = function(){
tinyMCE.init({
'editor_deselector' : prefix + o.id
});
container.parentNode.removeChild(container);
node.style.display = 'block';
}
my.edit = function(){
txtArea.value = node.innerHTML;
node.style.display = 'none';
node.parentNode.insertBefore(container, node);
var styles = '';
var styleRef = cm.getByAttr('rel', 'stylesheet');
for(var i = 0, ln = styleRef.length; i < ln; i++){
styles += (i > 0? ',' : '') + styleRef[i].href;
}
tinyMCE.init({
'height' : '100%',
'content_css' : styles + ',/sdtc-new/nc/interface/common/css/mce-editor.css',
'mode' : "specific_textareas",
'editor_selector' : prefix + o.id
});
}
init();
}
use this like :
new EditBlock({'onSave' : function(content){
page.content = content;
viewDepartment(page);
}, 'id':'depContent', 'act' : '/departments/setContent/', 'val' : page.id, 'params' : {buttonList : ['fontSize','bold','italic','underline','strikeThrough','html']}});
So ... again about problem. When first time start to edit that all works fine when click save - all works too (still exists some bugs but after saving I can click and start edit again) but when click cancel that editor is hide but when I click to edit again I have a empty edit area. I see to console and find that after canceling when I start editing again then I create new edit but old not destroy - only hidden.
I try to usetynyMCE.Editor class methods like hide and show and setContent and was a some result - after canceling I could edit egain but edit area was without styles and buttons.
Please help. If would be quaestion by code - I pleasure to answer.
Thanks.
Don't use hide() and show() here. You should shut down tinymce correctly in order to be able to reinitialize a tinymce editor with the same id as the first one.
To shut down an edtor instance use:
tinymce.execCommand('mceRemoveControl',true,'editor_id');
To reinitialize use
tinymce.execCommand('mceAddControl',true,'editor_id');
Please note!
These have since changed, you may have better luck with (for newer versions, 4+ I think):
try mceRemoveEditor and mceAddEditor instead...as in:
tinymce.execCommand('mceRemoveEditor',true,'editor_id');
tinymce.execCommand('mceAddEditor',true,'editor_id');

Getting a jQuery selector for an element

In psuedo code, this is what I want.
var selector = $(this).cssSelectorAsString(); // Made up method...
// selector is now something like: "html>body>ul>li>img[3]"
var element = $(selector);
The reason is that I need to pass this off to an external environment, where a string is my only way to exchange data. This external environment then needs to send back a result, along with what element to update. So I need to be able to serialize a unique CSS selector for every element on the page.
I noticed jquery has a selector method, but it does not appear to work in this context. It only works if the object was created with a selector. It does not work if the object was created with an HTML node object.
I see now that a plugin existed (with the same name I thought of too), but here's just some quick JavaScript I wrote. It takes no consideration to the ids or classes of elements – only the structure (and adds :eq(x) where a node name is ambiguous).
jQuery.fn.getPath = function () {
if (this.length != 1) throw 'Requires one element.';
var path, node = this;
while (node.length) {
var realNode = node[0], name = realNode.name;
if (!name) break;
name = name.toLowerCase();
var parent = node.parent();
var siblings = parent.children(name);
if (siblings.length > 1) {
name += ':eq(' + siblings.index(realNode) + ')';
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
};
(License: MIT)
TL;DR - this is a more complex problem than it seems and you should use a library.
This problem appears easy at the first glance, but it's trickier than it seems, just as replacing plain URLs with links is non-trivial. Some considerations:
Using descendant selectors vs. child selectors can lead to cases where the selector isn't unique.
Using :eq() limits the usefulness of the solution, as it will require jQuery
Using tag+nth-child selectors can result in unnecessarily long selectors
Not taking advantage of ids makes the selector less robust to changes in the page structure.
Further proof that the problem isn't as easy as it seems: there are 10+ libraries that generate CSS selectors, and the author of one of them has published this comparison.
jQuery-GetPath is a good starting point: it'll give you the item's ancestors, like this:
var path = $('#foo').getPath();
// e.g., "html > body > div#bar > ul#abc.def.ghi > li#foo"
Here's a version of Blixt's answer that works in IE:
jQuery.fn.getPath = function () {
if (this.length != 1) throw 'Requires one element.';
var path, node = this;
while (node.length) {
var realNode = node[0];
var name = (
// IE9 and non-IE
realNode.localName ||
// IE <= 8
realNode.tagName ||
realNode.nodeName
);
// on IE8, nodeName is '#document' at the top level, but we don't need that
if (!name || name == '#document') break;
name = name.toLowerCase();
if (realNode.id) {
// As soon as an id is found, there's no need to specify more.
return name + '#' + realNode.id + (path ? '>' + path : '');
} else if (realNode.className) {
name += '.' + realNode.className.split(/\s+/).join('.');
}
var parent = node.parent(), siblings = parent.children(name);
if (siblings.length > 1) name += ':eq(' + siblings.index(node) + ')';
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
};
I just wanted to share my version too because it is very clear to understand. I tested this script in all common browsers and it is working like a boss.
jQuery.fn.getPath = function () {
var current = $(this);
var path = new Array();
var realpath = "BODY";
while ($(current).prop("tagName") != "BODY") {
var index = $(current).parent().find($(current).prop("tagName")).index($(current));
var name = $(current).prop("tagName");
var selector = " " + name + ":eq(" + index + ") ";
path.push(selector);
current = $(current).parent();
}
while (path.length != 0) {
realpath += path.pop();
}
return realpath;
}
Same solution like that one from #Blixt but compatible with multiple jQuery elements.
jQuery('.some-selector') can result in one or many DOM elements. #Blixt's solution works unfortunately only with the first one. My solution concatenates all them with ,.
If you want just handle the first element do it like this:
jQuery('.some-selector').first().getPath();
// or
jQuery('.some-selector:first').getPath();
Improved version
jQuery.fn.extend({
getPath: function() {
var pathes = [];
this.each(function(index, element) {
var path, $node = jQuery(element);
while ($node.length) {
var realNode = $node.get(0), name = realNode.localName;
if (!name) { break; }
name = name.toLowerCase();
var parent = $node.parent();
var sameTagSiblings = parent.children(name);
if (sameTagSiblings.length > 1)
{
allSiblings = parent.children();
var index = allSiblings.index(realNode) +1;
if (index > 0) {
name += ':nth-child(' + index + ')';
}
}
path = name + (path ? ' > ' + path : '');
$node = parent;
}
pathes.push(path);
});
return pathes.join(',');
}
});
If you are looking for a comprehensive, non-jQuery solution then you should try axe.utils.getSelector.
Following up on what alex wrote.
jQuery-GetPath is a great starting point but I have modified it a little to incorporate :eq(), allowing me to distinguish between multiple id-less elements.
Add this before the getPath return line:
if (typeof id == 'undefined' && cur != 'body') {
allSiblings = $(this).parent().children(cur);
var index = allSiblings.index(this);// + 1;
//if (index > 0) {
cur += ':eq(' + index + ')';
//}
}
This will return a path like "html > body > ul#hello > li.5:eq(1)"
Update: This code was changed since then. You may find the implementation of the function now at css-login.js
Original answer:
You may also have a look at findCssSelector, which is used in Firefox developer tools to save the currently selected node upon page refreshes. It doesn't use jQuery or any library.
const findCssSelector = function(ele) {
ele = getRootBindingParent(ele);
let document = ele.ownerDocument;
if (!document || !document.contains(ele)) {
throw new Error("findCssSelector received element not inside document");
}
let cssEscape = ele.ownerGlobal.CSS.escape;
// document.querySelectorAll("#id") returns multiple if elements share an ID
if (ele.id &&
document.querySelectorAll("#" + cssEscape(ele.id)).length === 1) {
return "#" + cssEscape(ele.id);
}
// Inherently unique by tag name
let tagName = ele.localName;
if (tagName === "html") {
return "html";
}
if (tagName === "head") {
return "head";
}
if (tagName === "body") {
return "body";
}
// We might be able to find a unique class name
let selector, index, matches;
if (ele.classList.length > 0) {
for (let i = 0; i < ele.classList.length; i++) {
// Is this className unique by itself?
selector = "." + cssEscape(ele.classList.item(i));
matches = document.querySelectorAll(selector);
if (matches.length === 1) {
return selector;
}
// Maybe it's unique with a tag name?
selector = cssEscape(tagName) + selector;
matches = document.querySelectorAll(selector);
if (matches.length === 1) {
return selector;
}
// Maybe it's unique using a tag name and nth-child
index = positionInNodeList(ele, ele.parentNode.children) + 1;
selector = selector + ":nth-child(" + index + ")";
matches = document.querySelectorAll(selector);
if (matches.length === 1) {
return selector;
}
}
}
// Not unique enough yet. As long as it's not a child of the document,
// continue recursing up until it is unique enough.
if (ele.parentNode !== document) {
index = positionInNodeList(ele, ele.parentNode.children) + 1;
selector = findCssSelector(ele.parentNode) + " > " +
cssEscape(tagName) + ":nth-child(" + index + ")";
}
return selector;
};
$.fn.getSelector = function(){
var $ele = $(this);
return '#' + $ele.parents('[id!=""]').first().attr('id')
+ ' .' + $ele.attr('class');
};

Categories