what is closest function javascript? - javascript

I am trying to convert a jquery function to vanila js.I don't know the implementation of that function I just want to convert jquery function to javascript . here is my jquery function.
jQuery('button.vjs-share-control').on('touchstart click', function(e) {
e.preventDefault();
if(e.type == "touchstart") {
var embedDiv = jQuery(this).closest('div.bcvideo');
var vid = videojs(embedDiv.data('bcobjid'));
var shareopts = {
"services": setSocialLinks.call(embedDiv)
};
// set share links
vid.social(shareopts);
jQuery('#w10close').removeClass('hidden');
} else if(e.type == "click") {
var embedDiv = jQuery(this).closest('div.bcvideo');
var vid = videojs(embedDiv.data('bcobjid'));
var shareopts = {
"services": setSocialLinks.call(embedDiv)
};
// set share links
vid.social(shareopts);
jQuery('#w10close').removeClass('hidden');
}
});
I covert this function to javascript but I am confused by closest and call function how to convert these jquery function to javascript.
Here is my javascript function (converted jquery function to javascript)
document.querySelector('button.vjs-share-control').addEventListener('touchstart click', function(e) {
e.preventDefault();
if(e.type == "touchstart") {
var embedDiv = document.querySelector(this).closest('div.bcvideo');
var vid = videojs(embedDiv.data('bcobjid'));
var shareopts = {
"services": setSocialLinks.call(embedDiv)
};
// set share links
vid.social(shareopts);
document.querySelector('#w10close').classList.remove('hidden');
} else if(e.type == "click") {
var embedDiv = document.querySelector(this).closest('div.bcvideo');
var vid = videojs(embedDiv.data('bcobjid'));
var shareopts = {
"services": setSocialLinks.call(embedDiv)
};
// set share links
vid.social(shareopts);
document.querySelector('#w10close').classList.remove('hidden');
}
});
is it a right converted function ?

The Element.closest( ) function can be used to get the closest parent which satisfies the query condition. For example, in the below code, I have the tag and a inside the body tag, I have the same class attached to both and the tags.
Please run the below code and read the comments to understand how Element.closest( ) works in this case:
const inputField = document.querySelector('.textbox');
//logging the inputField variable
console.log(inputField);
//This retuns the <h1> because that is the closest parent
//with 'inner-parent' class.
console.log(inputField.closest('.inner-parent'));
//This returns the 'div' element instead of the 'body'
//although both have the same class, that is because <div>
//is closer to input element than the <body>
console.log(inputField.closest('.outer-parent'));
<body class = 'outer-parent'>
<div class='outer-parent'>
<h1 class='inner-parent' >
<input type='text' class='textbox'>
</h1>
</div>
</body>
Also, please note, that the closest( ) function only works on parents, you cannot use it to find parents or siblings directly. However, you can query the parent to get the sibling element if needed.

Related

Using JQuery on a window reference?

Can you use JQuery on a window reference? I have tried the following with no luck.
function GetDiPSWindow() {
var DiPSURL = "/DiPS/index";
var DiPSWindow = window.open("", "DiPS", "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=520,height=875");
if (DiPSWindow.location.href === "about:blank") {
DiPSWindow.location = DiPSURL;
}
return DiPSWindow;
}
function AddRecipient(field, nameId) {
// Get window
var win = GetDiPSWindow();
// Attempt 1
$(win.document).ready(function () {
var input = win.document.getElementById(field + "_Input");
input.value = nameId;
});
// Attempt 2
$(win).ready(function () {
var input = win.document.getElementById(field + "_Input");
input.value = nameId;
});
// Attempt 3
$(win).load(function () {
var input = win.document.getElementById(field + "_Input");
input.value = nameId;
});
}
Am I making a simple mistake?
EDIT For some reason, win.document.readyState is "complete". Not sure if that makes a difference.
I have also tried:
View contains:
<script>var CallbackFunction = function() {}; // Placeholder</script>
The method:
function AddRecipient(field, nameId) {
var DiPSURL = "/DiPS/index";
if (deliveryChannel === undefined) {
deliveryChannel = 0;
}
var DiPSWindow = GetDiPSWindow();
if (DiPSWindow.location.href === "about:blank") {
DiPSWindow.location = DiPSURL;
DiPSWindow.onload = function () { DiPSWindow.CallbackFunction = AddRecipient(field, nameId) }
} else {
var input = DiPSWindow.document.getElementById(field + "_Input");
input.value = input.value + nameId;
var event = new Event('change');
input.dispatchEvent(event);
}
}
The answer is.... kinda. it depends on what you are doing.
You can use jquery on the parent page to interact with a page within an iframe, however, anything that requires working with the iframe's document object may not work properly because jQuery keeps a reference of the document it was included on and uses it in various places, including when using document ready handlers. So, you can't bind to the document ready handler of the iframe, however you can bind other event handlers, and you can listen for the iframe's load event to know when it is absolutely safe to interact with it's document.
It would be easier though to just include jquery within the iframe itself and use it instead. It should be cached anyway, so there's no real detriment to performance by doing so.

Bind function with parameters to dynamically created element of dynamically added event

My question is little bit confuse. I created comment box to post comments in javascript. I am posting every comment using javascript by creating dynamically created elements, attributes and event handlers.
Javascript:
var commentSubmit = document.getElementById("commentSubmit"),
commentBox = document.getElementById("commentBox"),
deleteComment = document.getElementById("deleteComment"),
commentList = document.getElementById("commentList");
function getDataFromLocalStorage(){
var i = 0,
cArr = [],
cKey;
for (; cKey = window.localStorage.key(i); i++) {
var cObj = {};
cObj.cId = cKey;
cObj.cText = window.localStorage.getItem(cKey);
cArr.push(cObj);
}
return cArr;
}
function createElement(name,attr,events,html){
debugger;
var elem = document.createElement(name);
var elemText;
if(html){
for(var i=0;i<html.length;i++){
if(html[i].name == "text"){
elemText = document.createTextNode(html[i].value)
elem.appendChild(elemText);
}else{
elem.appendChild(html[i].value);
}
}
}
if(events){
for(var i=0;i<events.length;i++){
if(events[i]["customFunction"]){
elem.addEventListener(events[i].eventName,events[i]["customFunction"].bind(elem,events[i].eventParams.join(" ")),false);
}
}
}
for(var i=0;i<attr.length;i++){
elem.setAttribute(attr[i].name, attr[i].value);
}
return elem;
}
function deleteComment(cId){
localStorage.removeItem(cId);
loadComments();
}
function loadComments(){
var cComments = getDataFromLocalStorage(),
cTotal = cComments.length;
commentList.innerHTML = "";
if(cTotal){
for(var i=0;i<cTotal;i++){
var deleteCommentButton = createElement("BUTTON",
[
{name:"class",value:"deleteComment"},
{name:"id",value:"deleteComment"},
{name:"value",value:"X"}
],
[
{eventName:"onclick",eventParams:[cComments[i].cId],customFunction:"deleteComment"}
]
);
var commentWrapper = createElement("DIV",
[
{name:"class",value:"commentWrapper"},
{name:"id",value:cComments[i].cId}
],
[
{name:"text",value:cComments[i].cText},
{name:"html",value:deleteCommentButton}
]
);
/*var commentText = document.createTextNode(cComments[i].cText);
commentWrapper.setAttribute("class", "commentWrapper");
commentWrapper.setAttribute("id", cComments[i].cId);
commentWrapper.appendChild(commentText);*/
commentList.appendChild(commentWrapper);
}
}
}
loadComments();
commentSubmit.addEventListener("click", function(e){
var cKey = Date.now();
if(commentBox.value != ""){
localStorage.setItem(cKey,commentBox.value);
loadComments();
}
e.preventDefault();
return false;
}, false);
html:
<div class="commentForm">
<form>
<textarea rows=5 id=commentBox></textarea>
<button id=commentSubmit>Post</button>
</form>
</div>
<div id="commentList">
</div>
my question is
i want to attach deleteComment function to the dynamically created
element. here, i am sending the function name also dynamically. i was
unable to bind function.
here is jsfiddle
thanks in advance.
Don't set the listener to the function name. That's not how it works. Send the function itself:
{eventName:"onclick",eventParams:[cComments[i].cId],customFunction:deleteComment}
Also, depending on what exactly you want, joining the params may also not be what you REALLY want to do.
Additional answer:
Found a bug in your code:
{name:"id",value:"deleteComment"}
You're creating an HTML element (in this case a button) with the same name as a function. This causes the function to be deleted. This is a very weird feature that was introduced by IE that was copied by other browsers for compatibility with IE specific sites. Now it's part of the HTML5 specification :(
To fix this either rename your function or rename the element. See this edit for an example fix: http://jsfiddle.net/pcmyzhqu/10

Trigger addEventListener on live element that is not in the DOM (native JavaScript)

I'm stuck with my modal popup plugin since a week.
I'll try to explain as much as i can but first, here is the jsfiddle: http://jsfiddle.net/hideo/yth37hhf/27/
I know the code contains some other functions but they are useful for my plugin.
So, my issue is that the function "triggerLinkAction" contains an addEventListener which is not fired.
(function() {
Window.prototype.triggerLinkAction = function(){
var triggeredLink = document.getElementById("triggeredOtherAction");
var inputTarget = document.getElementById("inputText");
console.log('triggeredLink',triggeredLink);
triggeredLink.addEventListener("click", function (e) {
alert('If this pops out, I will be very happy!!!');
e.preventDefault();
inputTarget.value = "This text should be on the input field...";
}, true);
}
})();
The targeted element is inside the modal, and this modal is displayed by clicking on the link "A small modal".
When the plugin calls ShowModal(), I trigger the TransitionEnd event to call a function
[.... code ...]
function ShowModal() {
vars.popupContainer.classList.add("show");
hsdk.PrefixedEvent(vars.popupOverlay, "TransitionEnd", function (e) {
executeFunctions();
});
}
[.... code ...]
The executeFunctions() will check which functions need to be called:
[.... code ...]
function executeFunctions() {
if (vars.opts && vars.opts.fn) {
var allFunctions = vars.opts.fn.split(',');
for (var i = 0; i < allFunctions.length; i++)
{
var functionName = allFunctions[i];
var functionToExecute = window[functionName];
if(typeof functionToExecute === 'function') {
functionToExecute();
}
}
}
}
[.... code ...]
There are some comments on the javascript part about the plugin, but feel free to ask if I can provide any other information.
PS: I don't care about IE for now ;-)

Copy/Paste element with jQuery

I have a div that I'm appending to another div when a button is clicked. I'm also calling a bunch of functions on the div that gets created.
HTML
<a onClick="drawRect();">Rect</a>
JS
function drawRect(){
var elemRect = document.createElement('div');
elemRect.className = 'elem elemRect';
elemRect.style.position = "absolute";
elemRect.style.background = "#ecf0f1";
elemRect.style.width = "100%";
elemRect.style.height = "100%";
elemRect.style.opacity = "100";
renderUIObject(elemRect);
$('.elemContainer').draggableParent();
$('.elemContainer').resizableParent();
makeDeselectable();
handleDblClick();
}
var createDefaultElement = function() {
..
..
};
var handleDblClick = function() {
..
..
};
var renderUIObject = function(object) {
..
..
};
var makeDeselectable = function() {
..
..
};
I could clone the element when the browser detects a keydown event
$(window).keydown(function(e) {
if (e.keyCode == 77) {
$('.ui-selected').clone();
return false;
}
});
then append it to #canvas. But the problem is, none of the functions I mentioned above get called with this method.
How can I copy/paste an element (by pressing CMD+C then CMD+V) and call those above functions on the cloned element?
The jQuery.clone method returns the cloned node. So you could adjust your code to do something like this:
var myNodes = $('.ui-selected').clone();
myNodes.each(function () {
createDefaultElement(this);
appendResizeHandles(this);
appendOutline(this);
});

Can a JQuery plugin be called on a JQuery chain of methods or does it need to be called straight after a selector?

I'm having difficulty getting my textarea to expand vertically automatically.
I have some code to help make textarea auto expand vertically and for some reason it works when I clean out all my JS and provide a selector with reference to textarea e.g. $('textarea').autoGrow();
Calling the plugin on a chain of methods stops it from working. E.G.
micropostBox.hide().removeClass("micropost_content")
.addClass("micropost_content_expanded").show().autoGrow();
I established the plugin code works so copied all my working code to the same page and applied the autoGrow code to my textarea but it seems to be unresponsive. I noticed that the plugin I'm using the code from uses bind and unbind methods. In my code I use on and off methods from JQuery and wondering if this could be why the auto resizing of my textarea is not working?
Here is the code:
http://jsfiddle.net/erU5J/101/
autogrow plugin js code
$(function($) {
$.fn.autoGrow = function() {
return this.each(function() {
var txtArea = $(this);
var colsDefault = txtArea.attr('cols');
var rowsDefault = txtArea.attr('rows');
var updateSize = function() {
var linesCount = 0;
var lines = txtArea.attr('value').split('\n');
for (var i = lines.length - 1; i >= 0; --i) {
linesCount += Math.floor((lines[i].length / colsDefault) + 1);
}
if (linesCount >= rowsDefault) {
txtArea.attr('rows', linesCount + 1);
}
else {
txtArea.attr('rows', rowsDefault);
}
};
txtArea.unbind('.autoGrow').bind('keyup.autoGrow', updateSize).bind('keydown.autoGrow', updateSize).bind('change.autoGrow', updateSize);
});
};
});
my js code
$(function() {
$("div.microposts").on("focus", "textarea#micropostBox", function() {
var micropostForm = $(this).parent(),
micropostBox = micropostForm.find('textarea#micropostBox'),
micropostButton = micropostForm.find("input#micropostButton"),
xButton = micropostForm.find("div.xButton");
micropostBox.prop('rows', 7);
micropostForm.find('div#micropostOptions').removeClass('micropostExtraOptions');
micropostForm.find('div#postOptions').show();
$.trim(micropostBox.val()) == '' ? micropostButton.addClass("disabledMicropostButton").show()
:
micropostButton.prop('disabled', false);
micropostBox.hide().removeClass("micropost_content").addClass("micropost_content_expanded").show().autoGrow();
xButton.show();
micropostButton.prop('disabled', true);
micropostBox.off().on("keypress input change", function() {
micropostButton.prop({
disabled: !$.trim($(this).val()) != ''
});
$.trim($(this).val()) != '' ? micropostButton.removeClass("disabledMicropostButton").addClass("activeMicropostButton")
:
micropostButton.removeClass("activeMicropostButton").addClass("disabledMicropostButton");
});
xButton.on('click', function() {
micropostBox.removeClass("micropost_content_expanded").addClass("micropost_content");
micropostForm.find('div#micropostOptions').addClass('micropostExtraOptions');
micropostBox.val("");
micropostForm.find('div#postOptions').hide();
xButton.hide();
micropostButton.hide();
micropostBox.removeAttr('style');
micropostBox.prop('rows', 0);
micropostForm.find('.imagePreview > img').remove();
micropostForm.find('.imagePreview').hide();
});
});
});
$(function() {
$('div.microposts').on('click', 'li#addImage', function() {
var form = $(this).parents('form#new_micropost'),
fileField = form.find('input#micropost_image');
fileField.trigger('click');
});
});
$(function() {
$('input#micropost_image').change(function(evt) { //.off() make sautoresize work
var image = evt.target.files[0],
form = $(this).parents('form#new_micropost'),
imagePreviewBox = form.find('div.imagePreview'),
reader = new FileReader();
reader.onload = function(evt) {
var resultdata = evt.target.result,
img = new Image();
img.src = evt.target.result;
imagePreviewBox.show().prepend(img);
};
reader.readAsDataURL(image);
});
});​
textarea
<textarea class="micropost_content" cols="40" id="micropostBox" name="micropost[content]" placeholder="" rows="0"></textarea>
It would be best to view a working example on jsfiddle. My aim is to have the auto resizing of textarea working before and after an image is added to the page using the image upload button in the textarea.
Kind regards
It depends if the method preceding the plugin call returned the jQuery object containing the elements to where the plugins need to be attached.
Here are a few examples of methods that do and do not return the elements you started with:
$('element') //get an element
.contents() //get an elements contents
.wrapAll('<div>') //wrapAll contents with div and returns the contents, not wrapper
.parent() //the wrapper
.parent() //the element
.myPlugin() //we attach a plugin to element
$('<div>')
.appendTo('body') //appendTo returns the same element, the div
.myPlugin() //attaches to the div
$('element') //get an element
.text() //get its text
.myPlugin() //chaining isn't possible since text() returns a string
Better read the docs for every method in jQuery and what it returns. Some DOM methods usually return the same element, some don't, and some don't return elements but values.
In summary, can plugins be attached after chains? YES, and it depends.
Refer to the jQuery's documentation
http://docs.jquery.com/Plugins/Authoring#Maintaining_Chainability

Categories

Resources