Simulating click event inside JavaScript OnClick results in error - javascript

I am building a context menu with some options using <li> tags as shown below. I need to simulate click event on another ID (image), When i choose and click on this option from context menu.. I can only have the function instantaneous execution inside onclick as shown in below code-
Edited the code to give more clarity
var functionMain = function ContextMenu$functionMain(items, targetId) {
$(menu).html(buildItems(items, targetId));
};
var buildItems = function ContextMenu$buildItems(items, targetId) {
var i, result;
result = '';
for (i = 0; i < items.length; ++i) {
var reportId = targetId.substring(targetId.indexOf(':') + 1);
var reportIdFormed = $('#' + reportId + 'run' + runReportLinkName);
result += '<li> Run HTML </li>';
}
return result;
};
Above code is resulting in Uncaught SyntaxError: Unexpected identifier
Resultant HTML --> Run HTML
How to get rid of this issue?

Use a delegated event
var reportId = targetId.substring(targetId.indexOf(':') + 1);
var reportIdFormed = $('#' + reportId + 'run' + runReportLinkName);
result += '<li> Run HTML </li>';//add a class
$('body').on('click','.delegated-event',function(){ //delegate the event based on that class
reportIdFormed.trigger('click');
})
if the selector changes for each element then you need a attribute to store the selector:
var reportIdFormed = '#' + reportId + 'run' + runReportLinkName;//make it a string
result += '<li> Run HTML </li>';//add a class
$('body').on('click','.delegated-event',function(){ //delegate the event based on that class
reportIdFormed = $($(this).attr('data-selector'));//get the selector
reportIdFormed.trigger('click');
})

The problem with your code is that you are trying to pass and object referent instead and ID string, so you are printing that, so JS cannot print and JS object, so it will print the reference [object Object] so you should do it like so:
var reportId = targetId.substring(targetId.indexOf(':') + 1); //e.g. rpt1234
var reportIdFormed = '#' + reportId + 'run' + runReportLinkName; //e.g. rpt1234runHTML
result += '<li> Run HTML </li>';
Your code JS
function handleTrigger(id) {
var target = $(id);
if (target.length) {
target.trigger("click")
}
}

Try this
var reportId = targetId.substring(targetId.indexOf(':') + 1); //e.g. rpt1234
var reportIdFormed = reportId + 'run' + runReportLinkName; //e.g. rpt1234runHTML
result += '<li> Run HTML </li>';

Related

Error on close button with onclick javascript, maybe around quotes/single/double

I have a small Issue Tracker which uses a couple of functions to save and fetch issues to localStorage, all of which works fine, using the Chance uid generator to generate ids. However on making a third function to set the status to closed after getting the id which was generated previously. In console I get an error as below.
(function(event){setStatusClosed(fdf7622a-8738-5384-98b6-9ff9c47b2be0)
}) invalid or unexpected token. index.html:1
It's using onclick to run the function via the close button generated in the fetchIssues() function.
The first 2 functions fetchIssues() and saveIssues() have been working as expected with no errors and correctly converting the array to JSON object on push and back to array on retrieve, but when I try the setStatusClosed function I get the error. I also get similar errors when using other uid generator methods so I decided to stick with Chance. I can't seem to find the error and the log just points me to the event as pasted above. The code is below
/*jslint browser:true */
//Fetch submitted issues or the status of localStorage
function fetchIssues() {
"use strict";
var i = 0;
var issues = JSON.parse(localStorage.getItem("issues"));
var issueList = document.querySelector('#issueList');
issueList.innerHTML = " ";
if(issues !== null) {
for(i = 0; i < issues.length; i++) {
var id = issues[i].id,
desc = issues[i].description,
severity = issues[i].severity,
assignedTo = issues[i].assignedTo,
status = issues[i].status;
issueList.innerHTML += "<div class='well'>" +
"<h6>Issue ID: " + id + "</h6>" +
"<p><span class='Label label-info'>" + status + "</span></p>" +
"<h3>" + desc + "</h3>" +
"<p><span class='glyphicon glyphicon-time'></span>" + severity + "</p>" +
"<p><span class='glyphicon glyphicon-user'></span>" + assignedTo + "</p>" +
"<a href='#' onclick='setStatusClosed("+ id +")' class='btn btn-warning'>Close</a>" +
"<a href='#' onclick='deleteIssue(" + id + ")' class='btn btn-danger'>Delete</a>" +
"</div>";
}
console.log(issues);
} else {
issueList.innerHTML = "<h6 class='text-center'>There are no issues at present</h6>";
}
}
//Save a submitted issue
function saveIssue(e) {
"use strict";
var chance = new Chance();
var issueDesc = document.querySelector("#issueDescInput").value,
issueSeverity = document.querySelector("#issueSeverityInput").value,
issueAssignedTo = document.querySelector("#issueAssignedToInput").value,
issueStatus = "Open",
issueId = chance.guid(),
issues = [],
issue = {
id: issueId,
description: issueDesc,
severity: issueSeverity,
assignedTo: issueAssignedTo,
status: issueStatus
};
//Check if entry already there
if(localStorage.getItem("issues") === null) {
//Push the issue object to issues array
issues.push(issue);
//Set the new issues array as a converted JSON object to localStorage
localStorage.setItem("issues", JSON.stringify(issues));
} else {
//Request the issues object and convert to array
issues = JSON.parse(localStorage.getItem("issues"));
//Push new object to issues array
issues.push(issue);
//Set the new issues array as a converted JSON object to localStorage
localStorage.setItem("issues", JSON.stringify(issues));
}
//Reset submit element
document.querySelector("#issueInputForm").reset();
//Run fetchIssue to reflect the new item
fetchIssues();
//Stop default submit
e.preventDefault();
}
//Submit event for the saveIssue function
document.querySelector("#issueInputForm").addEventListener("submit", saveIssue);
//Set the issue status to closed
function setStatusClosed(id) {
var i;
var issues = JSON.parse(localStorage.getItem("issues"));
for(i = 0; i < issues.length; i++) {
if(issues[i].id == id) {
issues.status = "Closed";
}
}
localStorage.setItem("issues", JSON.stringify(issues));
fetchIssues();
}
It all compiles fine in the Closure compiler
The error appears only when hitting the close issue button, so does anyone know why the function is not being properly called in the onclick event (generated via innerHTML method) ?
Any tips welcome, Thanks
Update, I have tried altering the call in the generated innerHTML to escape the quotes but now I get a slightly different error that setStatusClosed() is not defined for the onclick event.(Also I removed Bootstrap so its just using the lib js file.), so there seems to be an error with the onclick call.
issueList.innerHTML += '<div class="well">' +
'<h6>Issue ID: ' + id + '</h6>' +
'<p><span class="Label label-info">' + status + '</span></p>' +
'<h4>' + desc + '</h4>' +
'<p><span class="icon icon-clock"></span> ' + severity + '</p>' +
'<p><span class="icon icon-user"></span> ' + assignedTo + '</p>' +
'Close' +
'Delete' +
'</div>';

InnerHTML does not outputs anchor elements but instead outputs current pg url. why?

In the following code, links_container.innerHTML = links; outputs http://localhost/pagination/js-pagination.html# instead of <a href='#'>Page 1</a>.
HTML
<div class="pagination-links"></div>
JS
function createLinks() {
var links_container = document.getElementsByClassName('pagination-links')[0];
for(i=1; i<=5; i++){
var link = document.createElement('a');
var txt = document.createTextNode('Page ' + i + " ");
link.setAttribute("href", "#");
link.appendChild(txt);
links_container.innerHTML = link;
}
}
Can anybuddy explain. why
innerHTML is a string property and thus takes a string as value. Your link is an element object and because of this it's implicitly converted to a string with its toString() method, which does indeed return the URL.
Here are two ways you can fix this:
Both of these solutions require you to clear the container before the for loop by running links_container.innerHTML = ''
Append the element with links_container.appendChild(link)
Use the outerHTML of the element object: links_container.innerHTML += link.outerHTML
The first option is the more appropriate one as it inserts the DOM element you created into the DOM directly. The second option converts your DOM element to a string and then forces the browser to create a new DOM element from that HTML. If there had been any event listeners added to the element they would've been lost.
Instead of setting innerHTML try calling appendChild. The link object is an element not an HTML string.
i.e. try changing:
links_container.innerHTML = links;
to
links_container.appendChild(link);
function createLinks() {
var links_container = document.getElementsByClassName('pagination-links')[0];
// clear out previous html
links_container.innerHTML = "";
for (i = 1; i <= 5; i++) {
var link = document.createElement('a');
var txt = document.createTextNode('Page ' + i + " ");
link.setAttribute("href", "#");
link.appendChild(txt);
// append link to container
links_container.appendChild(link);
}
}
createLinks();
<div class="pagination-links"></div>
Solution using innerHTML:
links_container.innerHTML += link.outerHTML;
or
links_container.innerHTML += "<a href='#'>Page " + i + " </a>"
function createLinks() {
var links_container = document.getElementsByClassName('pagination-links')[0];
// clear out previous html
links_container.innerHTML = "";
for (i = 1; i <= 5; i++) {
var link = document.createElement('a');
var txt = document.createTextNode('Page ' + i + " ");
link.setAttribute("href", "#");
link.appendChild(txt);
// add link
links_container.innerHTML += link.outerHTML;
// or you can use this instead of the above code
//links_container.innerHTML += "<a href='#'>Page " + i + " </a>";
}
}
createLinks();
<div class="pagination-links"></div>
Replace this line
links_container.innerHTML = links;
with
links_container.innerHTML = link;
as you do not have any links variable there.

Download of excel file is not working in Firefox but works in Chrome

I am trying to download an excel file on onclick event. It allow me to download excel file in chrome but not in Firefox. Not sure what is the issue. I am getting below error.
ReferenceError: event is not defined
Below is my javascript function
function hyperlinkFn(){
var htmlTbl="";
var htmlTbl1="";
var string = event.target.parentElement.name;
var tempString=[];
var temp= new Array();
for(var i=0;i<string.length;i++){
if(string[i]=="|"){
temp.push(tempString);
tempString=[];
}else{
tempString+=string[i];
}
}
userStoryModalRelease = temp[0];
userStoryModalPID = temp[1];
userStoryModalPrjName = encodeURIComponent(temp[2]);
userStoryModalTeam = encodeURIComponent(temp[3]);
userStoryAltId=encodeURIComponent(temp[4]);
userStoryModalStatus = temp[5];
userStoryModalTeam = userStoryModalTeam.replace(", ", ",");
var uri="getUserStoryDetails.htm?release=" + userStoryModalRelease + "&projectId=" + userStoryModalPID + "&projectName=" + userStoryModalPrjName +
"&team=" + userStoryModalTeam + "&alternateId=" + userStoryAltId + "&view=" + storyView;
var encode = encodeURI(uri);
window.location = encode;
}
HTML code where I am calling this function in the datatable
{
title : "Total Points",
data : function(data, type, row, meta) {
return data.totalSum+'<a name="'+ data.releaseNum +'|'+ data.projectId +'|'+ data.projectName +'|'+ data.team + '|'+ data.altId + '|total|'+'" onclick="hyperlinkFn()">'
+ '<i class="fa fa-file-excel-o font-size-15 " title="Click here to export details " aria-hidden="true"></i></a>';
},
className : "center storypoint yellow_fill pos-rel"
} ],
Change your click binding like below so that event will work:
$(document).on('click', '.classname', function(event){
var htmlTbl="";
var htmlTbl1="";
var string = event.target.parentElement.name;
var tempString=[];
var temp= new Array();
for(var i=0;i<string.length;i++){
if(string[i]=="|"){
temp.push(tempString);
tempString=[];
}else{
tempString+=string[i];
}
}
userStoryModalRelease = temp[0];
userStoryModalPID = temp[1];
userStoryModalPrjName = encodeURIComponent(temp[2]);
userStoryModalTeam = encodeURIComponent(temp[3]);
userStoryAltId=encodeURIComponent(temp[4]);
userStoryModalStatus = temp[5];
userStoryModalTeam = userStoryModalTeam.replace(", ", ",");
var uri="getUserStoryDetails.htm?release=" + userStoryModalRelease + "&projectId=" + userStoryModalPID + "&projectName=" + userStoryModalPrjName +
"&team=" + userStoryModalTeam + "&alternateId=" + userStoryAltId + "&view=" + storyView;
var encode = encodeURI(uri);
window.location = encode;
})
Note: remove onclick event from hyperlink and add class on hyperlink and replace that classname with .classname
Looks like this has already been covered here:
ReferenceError: event is not defined error in Firefox
WebKit follows IE's old behavior of using a global symbol for "event", but
Firefox doesn't. When you're using jQuery, that library normalizes the
behavior and ensures that your event handlers are passed the event
parameter.
function hyperlinkFn(){ needs to become function hyperlinkFn( event ){

Creating a list of students and assigning a function to each button

I am trying to allow clients to create a list of students then view more info by simply clicking on the button with the students name. I've got it to create the button and display the students name in the button but it only calls the function when I click submit to add the student to the list, the actual student button doesn't seem to function.
function updateStudentList() {
var html = "";
for (var i = 0; i < students.length; i++) {
html += "<li><button type='button' class='studentButton'" + "id=" + students[i].name +">" + students[i].name + "</button></li>";
}
$('#studentList').html(html);
for (var i = 0; i < students.length; i++) {
document.getElementById(students[i].name).addEventListener('click', openStudentInfo(students[i].name));
}
}
function openStudentInfo(studentName) {
console.log("Opening " + studentName + " info.");
var studentInfo = requestStudentByName(studentName);
if (studentInfo != null) {
var studentInfoForm = $("#studentInfoForm");
var html = "";
html += "<h3>Student Name: " + studentInfo.name + "</h3>";
html += "<h3>Student ID: " + studentInfo.studentID + "</h3>";
studentInfoForm.html(html);
$("#studentInfoModal").show();
}
}
HTML:
<ul data-role="listview" id="studentList"> </ul>
Note: I can't use the onclick tag in HTML, it causes security issues. Cordova also blocks this.
The way you binding the event is not ok. Try binding this way:
$(document).ready(function() {
$("#studentList").on("click", ".studentButton", function() {
var studentId = $(this).data("studentid");
openStudentInfo(studentId);
});
});
And in your HTML generation:
html += "<li><button type='button' class='studentButton' data-studentid='" + students[i].studentID +"'>" + students[i].name + "</button></li>";
This kind of event delagation works not metter how you create the elements inside the root element(studentList in this case), because the event was bound in it, and not on the dynamic elements.
no jquery version of DontVoteMeDown's answer
document.getElementById('studentList').addEventListener('click', function(event) {
var clickedEl = event.target;
if(clickedEl.className === 'studentButton') {
var studentId = clickedEl.dataset.studentId;
openStudentInfo(studentId);
}
});

Javascript attach new property to element

I have an object, X, and some code that creates a div and assigns id = X.ID. After the html is created, I assign the object to the div, like this:
document.getElementById(X.ID).XValue = X;
If I set a break after that statement, I can evaulate document.getElementById(X.ID).XValue and see all the properties of X.
While I was creating the html, I added onmouseup="MOUSE_UP(event)".
var aProp = {};
aProp.ThisValue = "This";
aProp.ThatValue = "That";
aProp.Id = 5;
var html = '<div id="' + aProp.Id + '"';
var func = 'MOUSE_UP';
html += ' onmouseup="' + func + '(event) ">';
html += '</div>';
document.getElementById("test").innerHTML += html;
document.getElementById(aProp.Id).XVALUE = aProp;
function MOUSE_UP(event) {
alert(event.currentTarget.XValue.ThisValue);
}
Now, when I set a break at MOUSE_UP, event.currentTarget is my div (event.currentTarget.id == X.ID), but event.currentTarget.XValue is undefined.
Why is XValue undefined here when it was defined earlier?
Looks like setting innerHTML of #test would wipe out all custom properties from its children. You can check this in the jsFiddle. When you'll run the fiddle as it is, you'll notice NewProp of #1 will become undefined after adding more content with test.innerHTML += ... If you log tabIndex instead of NewProp, you'll get the correct values.
This happens because += operator is just a shortcut for a statement like a = a + b, which can also be written a += b.
Basicly you create a string from the inner HTML of #test, then add another string to it, and finally replace the original innerHTML of #test with this new string. All previous elements in #test are replaced with new ones, which don't have the custom properties set.
When setting id property for an element, also id attribute is added to the HTML, hence they are a part of innerHTML of #test, and are added to the newly created HTML too.
If you use proper DOM manipulation instead of setting innerHTML, you'll get the results you want. The code below uses createElement() and appendChild() methods instead of setting innerHTML.
function myMouseUp(e) {
alert("at MouseUp " + e.currentTarget.NewProp.ThisValue);
}
function buildOneDiv(aProp) {
var html = document.createElement('div');
aProp.ThisValue = 'This is ' + aProp.id;
aProp.ThatValue = 'That is ' + aProp.id;
html.id = aProp.id;
html.addEventListener('mouseup', myMouseUp, false);
html.innerHTML = 'Test ' + aProp.id;
return html;
}
function buildDivs(x) {
var html = buildOneDiv(x);
document.getElementById("test").appendChild(html);
document.getElementById(x.id).NewProp = x;
}
window.onload = function () {
var aProp, i;
for (i = 1; i < 4; i++) {
aProp = {};
aProp.id = i;
buildDivs(aProp);
}
};
A live demo at jsFiddle.
This is not so much an answer as it is a clarification and a work-around.
Given this html
<div id="test"></div>
and this code
function myMouseUp(e) {
alert("at MouseUp " + e.currentTarget.NewProp.ThisValue);
}
function buildOneDiv(aProp) {
aProp.ThisValue = "This";
aProp.ThatValue = "That";
var html = '<div id="' + aProp.id + '"';
var func = 'myMouseUp';
html += ' onmouseup="' + func + '(event) ">';
html += 'Test ' + aProp.id + '</div>';
return html;
}
function buildDivs(x) {
var html = buildOneDiv(x);
document.getElementById("test").innerHTML += html;
document.getElementById( x.id ).NewProp = x;
}
window.onload = function () {
for (var i = 1; i < 4; i++) {
var aProp = {};
aProp.id = i;
buildDivs(aProp);
}
};
The end result is that only the LAST div whose onmouseup is defined will have a legitimate value for NewProp at myMouseUp. For each other div, this property is undefined. This is why I got some comments indicating that "It does work." It works for ONE, which is all I had in my example. (This is the clarification.)
My workaround is to add a global object to be an associative array and change two statements:
var myDivs = {}; // global
Replace
document.getElementById( x.id ).NewProp = x;
in buildDivs with
myDivs[x.id] = x;
and replace
alert("at MouseUp " + e.currentTarget.NewProp.ThisValue);
in myMouseUp with
alert(myDivs[e.currentTarget.id].ThisValue );.
I'd still like to know why the original approach doesn't work.

Categories