I wrote a datepicker in Javascript, but it is not working properly,
as I lose the reference to the Calendar object.
here is the example
http://asexpress.de/calendar/
by clicking within the input field the calendar will be displayed.
What should I do that the reference to the Calendar object remains in contact.
From what I can tell so far of your script, the following code block:
Kalender.prototype.writeMonth = function() {
var that = this;
contains some code further down:
else if ( this.isToday(displayNum, length) && this.isLink(displayNum, length) )
{
sbuffer.push('<td class="date" onClick="that.changeDate(this,\''
+ this.id + '\'); that.returnDate('+ this.month +','+ this.year+')">' + displayNum + '</td>');
}
This would cause a problem, since the that variable is declared within the scope of this function and the onclick event will fire outside of the scope. IMO, building the HTML isn't the best method here. It would be best to build the table cells using the DOM and add event handlers that are inside the scope of the function. This happens a few times.
FYI, you're using eval() rather unnecessarily in your code:
this.months = eval("config.language."+ this.options['language'] +".months");
// Can also be written as:
this.months = config.language[this.options['language']].months;
See Eval is Evil for more information.
Further Reading
MSDN - Building Tables Dynamically
MDC - Traversing an HTML table with JavaScript and DOM Interfaces
MDC - Working with Closures
You should declare the variable which holds datepicker object globally.
var kalender;
var kalender2;
function reisedate(d) {
document.getElementById("abc").value = d.getDate() + "/" + parseInt(d.getMonth()+1) + "/" + d.getFullYear();
}
// rest of the code
Take a look at first two lines.
Related
I am building a vue component and I want to call a function defined in Vue methods by calling the onClick attribute when modifying innerHTML. However, it gives me error, "showModal is not defined" as shown below.
Here is my showModal function, I am just trying to console some data to make sure that the function is called:
methods: {
showModal: function() {
console.log("function is called")
//this.$refs.myModalRef.show();
//this.account=account;
}
}
and here is where i am trying to call that function in js by onclick function:
var inputText = document.getElementById("fileContents");
var innerHTML = inputText.innerHTML;
for(var i=0;i<this.violations.length;i++){
var index=innerHTML.indexOf(this.violations[i]);
if(index>0) {
innerHTML = innerHTML.substring(0, index) +"" + innerHTML.substring(index, index + this.violations[i].length) + "</span>" + "" + innerHTML.substring(index + this.violations[i].length);
inputText.innerHTML = innerHTML;
}
}
error: (index):1 Uncaught ReferenceError: showModal is not defined
at HTMLAnchorElement.onclick ((index):1)
Am I calling it in a wrong way?
Thanks!
Edit:
Thanks to #Ferrybig - I know I am able to call the function, however I have another problem; I want to pass the current word that I am changing its html to the funciton like this: onclick='myMethod(violations[i])' I tried setting this.violations array to be global like this:
window.violations=this.violations;
but again, (variable i) which is the index of current word in the array, is not global variable to be passed to 'myMethod' and it says (i is not defined). I cannot set i to global variable because it's an index incremented each time in the loop.
I thought about sending the current index of the tag I am editing to the function, 'myMethod', so I can track which tag I am in and its known by the html in the vue component but not sure how to do that..
Any other suggestions?
When using Vue templates, you get access to easy to use syntaxes that decrease programming time, and it is highly recommended that you start renderering your page using Vue instead.
In the case you are unable to use Vue for renderering your page, you can still use other bad techniques:
First, start by adding a created lifecycle method for created that moves a reference for your Vue method up to the global scope: created(){window.myMethod =this.myMethod;}
Since we then added the method to the global scope, you can just reference it using mymethod inside your vanilla onclick handler.
Note that the above workaround does not support multiple instances of your Vue component, but supporting this becomes way harder, and you should really use proper Vue components in that case.
Hi Just try to remove href='#' and instead add href="javascript:void(0)" along with #click="showModal"
This may help
You are not using a Vue handler in your call. Change onclick to #click
so:
#click="showModal"
or, alternatively,
v-on:click="showModal"
You have to use Vue syntax onClick like Method Event Handlers
So
innerHTML = innerHTML.substring(0, index) +"" + innerHTML.substring(index, index + this.violations[i].length) + "</span>" + "" + innerHTML.substring(index + this.violations[i].length);
need change to
innerHTML = innerHTML.substring(0, index) +""+ "<span style=\"background-color: yellow\">" + innerHTML.substring(index, index + this.violations[i].length) + "</span>" + "" + innerHTML.substring(index + this.violations[i].length);
I have a copy button that has:
$scope.copyHeadline = function (headline) {
var headlineCopy = headline;
var current_time = Date.now();
headlineCopy.label = headline.label + ' (Copy ' + current_time + ')';
$scope.headlineList.push(headlineCopy);
}
but I get the "Duplicates in a repeater are not allowed" error. I notice that everyone element in the array or list that i have has some sort of hidden property like:
$$hashKey: "object:135"
which i'm pretty sure is what it's duplicating but I can't change?
I read that I can use:
track by $index
but what ends up happening is that when I push the Copy button, it also edits the original element that I was copying as well so that doesn't work..
I was also of thinking of just creating a whole new element and writing a function that'll literally copy every element into a new one.. but this Class alone has several subclasses with ALOT of properties. So i guess I just wanted to see if there was an easier of doing it before I resort to that method. Thanks!
That is happening because just assigning a reference of the original object to a different variable will not make a copy of it. It just copies the reference to the same object.
AngularJS copy documentation
Use:
var headlineCopy = angular.copy(headline);
This will make a deep copy of the object.
Your problem stems from the fact that you are not copying your headline object, merely referencing it.
It's difficult to know the full solution without knowing more about your headline objects, but you could try something like this:
$scope.copyHeadline = function (headline) {
var headlineCopy = {};
var current_time = Date.now();
headlineCopy.label = headline.label + ' (Copy ' + current_time + ')';
$scope.headlineList.push(headlineCopy);
}
I am running into a problem people have posted before: JavaScript dynamic parameters
But my code uses nodes rather than innerHTML assignments, so the existing SO post doesn't seem to apply to my code.
I want to dynamically generate HTML buttons in a table. For each button, I want to call a function with parameters that depend on the button's index/position in the table. First I tried just using lambda functions with the variable over which I was incrementing. This didn't work, so I also tried dynamically named variables, meaning each button should be passing a differently named variable to deal with lazy-loading effects. But this didn't work either. You can see both versions of what I tried in the code below:
This code I paste below is in a for-loop. In the following, I increase i by 1 each time. offset and jj are unchanged within the loop.
var variableDynamic = i.toString();
window['variableName' + variableDynamic] = i + offset;
upvote.onclick = function() {
upVoteA(i + offset, jj);
//upVoteA(window['variableName' + variableDynamic] , jj);
};
upvote.innerHTML = "Upvote"
Someone told me to look into closures, so following this recommendation: http://www.usepatterns.com/blog/javascript-closures I rewrote the onclick function declaration as:
upvote.onclick = function() {
var a = i + offset;
var b = kk;
function closeIt(){
upVoteA(a,b);
}
closeIt();
};
This still has the same effect that every button calls upVoteA with the same parameter, namely the last/highest value.
I realize I could refactor my code to turn these into .innerHTML set statements and then I'd print the variable and it would be set as a printed statement instead of a lazily-loaded variable. But I'd like not to do that if possible. (apologies that it's not technically lazy loading, the name seems reasonably apt)
Is there a way to make my code work? And why are the closures failing? I thought closures should preserve the environment they were created in, but that is not the case with my code. Which portion of the "environment" are preserved with closures?
This is a very bad answer, but it works
var funcStr = "function dummy() { upVoteA(" + (i + offset) + "," + jj + "); }";
eval(funcStr);
upvote.onclick = dummy;
But if you have something better, please let me know.
Playing with some jQuery bits and pieces, I can't seem to get it quite right.
What I'm looking to do is loop through the items on a page, and apply a custom click handler to them. This way when I populate the page I just need to fill out the correct ID and the jQuery can automate filling in the link.
The problem I have is both events are firing with the same output, and I can't work out why. I have 2 which I am using as buttons,
<img id="LightButton11Of" src="images/lightbulb_off.png" style="width:32px;
height:32px; vertical-align:middle " alt="off" >
<img id="LightButton11On" src="images/lightbulb_on.png" style="width:32px;
height:32px; vertical-align:middle" alt="on">
and the following code
$(document).ready(function(){
$("[id^=LightButton]").each(function(i,item){
if ($(this).attr('id').substr(13,2)=="On"){lightfunction="1";}
if ($(this).attr('id').substr(13,2)=="Of"){lightfunction="0";}
alert($(this).attr('id').substr(13,2));
numLight = $(this).attr('id').substr(11,2);
strLight = "*1*" + lightfunction + "*" + numLight + "##";
teststr = $(item).attr('id') + " - " + strLight;
alert(teststr);
$(this).bind("click",function(){
SendEvent("OWN","18",strLight,"OK");
});
});
});
The alert(teststr) gives exactly the output I'm expecting, but it seems when I'm binding it is actually binding to all elements and not just the singular item from that iteration of the each loop.
What am I doing wrong!?
Cheers,
Tim.
What am I doing wrong!?
Your variables are all global.
This code in the click handler:
SendEvent("OWN","18",strLight,"OK");
...refers to the global variable strLight, which will have the value set in the last iteration of your .each() loop.
You should declare all of your variables with var, which will make them local to the function, so then each of the click handlers will use the local variable from its containing scope. (Which, thanks to the "magic" of closures, will still exist even though your each callback will have finished by the time the click events occur.)
$("[id^=LightButton]").each(function(i,item){
var lightfunction = this.id.substr(13,2)=="On" ? "1" : "0";
var numLight = this.id.substr(11,2);
var strLight = "*1*" + lightfunction + "*" + numLight + "##";
$(this).bind("click",function(){
SendEvent("OWN","18",strLight,"OK");
});
});
(Note also that there's no need to use $(this).attr('id') when this.id gives you the same value in a way that is faster to type, read and execute, and it's neater to set the value of lightfunction using a ternary operator instead of two if statements.)
I'm experiencing a problem when I attempt to use the .change() event on select lists, using the jQuery .toChecklist plugin.
My page contains a number of select lists, which are changed to CheckLists, using jQuery.
Consider the following Javascript snippet:
for (var i=0;i<5;i++)
{
var selectListId = 'selectList' + i;
// Assume this line represents the outputting on a
// standard select list
// Convert to Checklist
$("#" + selectListId).toChecklist();
$("#" + selectListId).change
(
function ()
{
alert("SelectListId: " + selectListId);
}
);
}
For each iteration of this loop, I output a multi-select list, convert it to Checklist, and then add the .change() handler.
However, when the page renders (visually, everything is fine), choosing an option from ANY of the lists gives the alert text of "SelectListId: selectList4" (ie. the last list id of the loop). Thus it appears that each invocation of .change() globally replaces the change handler.
Does anyone know how to change the code so that each checklist has its own change handler (so that the first change handler would output "SelectListId: selectList0", etc).
Thanks,
Try pulling the change function out of the loop. I also added a line that adds a class to each list. The new change function references the lists by the class and will know which is actively being changed via this.
for (var i = 0; i < 5; i++) {
var selectListId = 'selectList' + i;
$("#" + selectListId).toChecklist();
$("#" + selectListId).addClass('newChecklist');
}
$('.newChecklist').change(function() {
alert( $(this).attr('id') );
});
So, after a lot of head scratching, I've found a work-around for this issue.
While concatenating strings together in the anonymous function behaves in an unexpected manner, quoting the whole line of code and wrapping it in an eval statement produces the required results.
Thus, instead of writing, as above:
$("#" + selectListId).change
(
function ()
{
alert("SelectListId: " + selectListId);
}
)
You would need to write this instead:
eval('$("#' + selectListId + '").change(function (){alert("SelectListId: ' + selectListId + '");});');
This may not be the best approach, but it works, and for now that's good enough! :-)