How to solve this error?
===plugin.js
(function($) {
$.fn.myjqueryplugin = function(options) {};
$.fn.func1 = function() {
return this;
};
}(jQuery));
===base.js
$(document).ready(function() {
my_plugin = $("#myid").myjqueryplugin();
});
===hello.js
$(document).ready(function() {
my_plugin.func1();
});
===BUILD file
Properly define 3 js files with correct order.
Closure compiler error on hello.js
[JSC_POSSIBLE_INEXISTENT_PROPERTY] Property func1 never defined on *
How Closure compiler is able to find 'func1'?
Related
I have an EventListener that listens to the entire document and records keystrokes, but I want to remove this Listener when certain conditions are met.
The following is a snippet of my code:
document.addEventListener('keyup', function(e) {
var letter_entered = String.fromCharCode(e.keyCode).toLowerCase();
player.makeGuess(letter_entered);
if(player.win_status === true || player.lose_status === true) {
document.removeEventListener('keyup', arguments.callee, false);
}
});
This works, however according to the Mozilla Developer Docs this method has been deprecated.
I'm aware that I can simply name the function, but is there an alternative that would allow me to continue using the unnamed function?
Use the following process:
Create a variable
Assign an anonymous function to the variable
Invoke it with the variable reference
The anonymous function references itself using the variable name
Use it as such:
var foo = function(e)
{
"use strict";
console.log(e);
document.removeEventListener('keyup', foo, false);
}
document.addEventListener('keyup', foo);
You can solve this problem easily using the y combinator:
function y(f) {
return function () {
return f.bind(null, y(f)).apply(this, arguments);
};
}
Now you can rewrite your code as follows:
document.addEventListener("keyup", y(function (callee, e) {
player.makeGuess(String.fromCharCode(e.keyCode).toLowerCase());
if (player.win_status || player.lose_status) document
.removeEventListener("keyup", callee);
}));
That's all folks.
Use another anonymous function as a wrapper to store a named function (callee shim) to your original function:
document.addEventListener('keyup', (function(e)
{
var aFunction = function()
{
var letter_entered = String.fromCharCode(e.keyCode).toLowerCase();
player.makeGuess(letter_entered);
};
if(player.win_status === true || player.lose_status === true)
{
document.removeEventListener('keyup', window, false);
}
else
{
aFunction();
}
}
), false);
References
Strict Mode is Coming to Town
ES3.1:arguments.callee
Recursion with anonymous (inline) functions in XPath 3.0
Recursion with anonymous (inline) functions in XPath 3.0, Part II
I am using Meteor for Windows. I am trying to run a function in breadcrumb.js which is located in /client/lib
and I keep getting this error. ReferenceError: initBreadcrumb is not defined. I am a Java programmer and I am not sure if I am just trying to call intiBreadcrumb() wrong or if there is just something weird with Meteor that I am not used to.
I reference it in index.js like so:
if (Meteor.isClient) {
// counter starts at 0
Session.setDefault('json', "Hello");
Template.div1.created = function() {
initBreadcrumb();
}
}
Here is the breadcrumb.js code:
var breadcrumbList;
var crumbItems = [];
var variableCrumb;
function initBreadcrumb() {
var breadcrumb=$('<div>');
breadcrumb.addClass('breadcrumb');
breadcrumbList=$('<ul>');
breadcrumbList.addClass('breadcrumb_list');
breadcrumbList.appendTo(breadcrumb);
// Always add homepage icon
var homeIcon=$("<img>");
homeIcon.attr('alt','Homepage');
homeIcon.attr('src','../../public/images/home.png');
addCrumb('index.html', homeIcon, 'breadcrumb_first');
breadcrumb.prependTo($('body'));
}
function addCrumb(link, content, className) {
var newListItem=$('<li>');
if (className != undefined)
newListItem.addClass(className);
var newLink=$('<a>');
newLink.attr('href', link);
content.appendTo(newLink);
newLink.appendTo(newListItem);
newListItem.appendTo(breadcrumbList);
crumbItems.push(newListItem);
}
function addTextCrumb(linkHref, linkText) {
var newLink=$('<a>').text(linkText);
addCrumb(linkHref, newLink, 'breadcrumb_text');
return newLink
}
/***
* Set the "variable" crumb - i.e. the page content crumb
*/
function setVariableCrumb(linkHref, linkText) {
if (variableCrumb == undefined) {
variableCrumb=addTextCrumb(linkHref, linkText);
} else {
variableCrumb.text(linkText);
variableCrumb.attr('href', linkHref);
}
}
You have to understand how JavaScript scope works. There is global and local scope. Meteor wraps all *.js files by function (closure):
(function() {
//local function
function yourFunction() {
//code
}
})()
So your functions becomes local ones.
If you want to define global function in closure you need to define it as global variable:
(function() {
//global function
yourFunction = function() {
//code
}
})()
You have to change the function definition code.
initBreadcrumb = function(){...};
addCrumb = function(link, content, className){...};
addTextCrumb = function(linkHref, linkText){...};
...
Then your function can be run in your template code.
This will make your function to global.
In Facebook react.js, you can compose component within component, or maybe mix and match.
I'm wondering if twitter flight can do the same thing. if so, can anyone gives me an example?
this is what I have so far:
define(function (require) {
var defineComponent = require('flight/lib/component'),
infoInput = require('component/info_input');
return defineComponent(inputSection, infoInput);
function inputSection () {
this.after('initialize', function() {
infoInput.doSomehting();
});
};
});
and my info_input.js is defined below:
define(function (require) {
var defineComponent = require('flight/lib/component');
return defineComponent(infoInput);
function infoInput() {
this.after('initialize', function() {
});
this.doSomething = function() {
alert('I will do something');
};
};
});
This is what mixins are for.
Flight Components are enriched mixins.
From doc/component_api.md
It comes with a set of basic functionality such as event handling and Component registration. Each Component definition mixes in a set of custom properties which describe its behavior.
Read more about Components.
So the answer to your question is Yes.
I guess that what you are doing is legit, although I've never done it before.
I'd rather move the shared logic to a Mixin or attach the two components to the same element and let them talk via events:
component/input_section.js
this.after('initialize', function () {
this.trigger('uiSomethingRequired');
});
component/info_input.js
this.after('initialize', function () {
this.on('uiSomethingRequired', this.doSomething);
});
Solution mentioned by G.G above works!
We may go a step ahead to trigger events on restricted scope instead of document:
component/input_section.js
this.after('initialize', function () {
this.$node.closest(this.attr.parentClass).trigger('uiSomethingRequired');
});
component/info_input.js
this.after('initialize', function () {
this.on(this.$node.closest(this.attr.parentClass), 'uiSomethingRequired', this.doSomething);
});
I've been having a problem using an RSS parser in meteor. It's an async call, so it needs ot be wrapped, however it still doesn't seem to work. I presume this is because the anonymous on('readable' function is outside the fiber, but I can't see how to resolve it.
var FeedParser = Meteor.require('feedparser');
var request = Meteor.require('request');
function getBlog(url, parameter, id){
request(parameter)
.on('error', function (error) {
console.error(error);
})
.pipe(new FeedParser())
.on('error', function (error) {
console.error(error);
})
.on('readable', function () {
var stream = this,
item;
while (item = stream.read()) {
Items.insert(new_item);
}
});
}
var wrappedGetBlog = Meteor._wrapAsync(getBlog);
Meteor.methods({
blog: function (url, parameter, id) {
console.log('parsing blog');
var items = wrappedGetBlog(url, parameter, id);
}
});
Meteor._wrapAsync() expects the wrapped function to return error and result to a callback. Your function, getBlog(), does not do that so _wrapAsync is not the right approach.
I have wrapped that function before but used a Future.
That approach allowed me to call feedparser from a Meteor.method(), which doesn't allow async functions, but you are also trying to do an insert inside the readable event. I think that insert will complain if it is not in a fiber. Maybe like this would also be necessary:
var r = request( parameter );
r.on( 'response' , function(){
var fp = r.pipe( new FeedParser() ); //need feedparser object as variable to pass to bindEnvironment
fp.on('readable', Meteor.bindEnvironment(
function () {
var stream = this,
item;
while (item = stream.read()) {
Items.insert(new_item);
}
}
, function( error ){ console.log( error );}
, fp // variable applied as `this` inside call of first function
));
});
Fibers is another option...
var Fiber = Npm.require( "fibers" );
.on('readable', function () {
var stream = this,
item;
while (item = stream.read()) {
Fiber( function(){
Items.insert(new_item);
Fiber.yield();
}).run();
}
});
I don't know why but this code is not working ? Why would it not ? I guess it is because scope problem I am having here :
function washAway(obj) {
alert($(obj)); // says HTML Object which is fine
setTimeout(function() {
alert($(obj)); // says undefined
$(obj).fadeOut("slow", function() {
$(this).remove();
});
}, 2000);
};
At the point where the function in the timeout executes, it has no way to know what obj is - it was a parameter passed into the method where the timeout was set up, but the function inside has no reference to it.
An alternative approach is to write a jQuery plugin to wait before it acts like this:
function($){ //to protect $ from noConflict()
$.fn.pause = function(duration) {
$(this).animate({ dummy: 1 }, duration);
return this;
};
}
Then you can use:
$(obj).pause(2000).fadeOut("slow", function() { $(this).remove(); });
Any ways, I've found my answer after a couple of try/wrong. But I am still wondering why it didn't work out.
Here is the code :
function washAway(obj) {
alert($(obj).attr("id"));
var a = function() {
var _obj = obj;
return function() {
$(_obj).fadeOut("slow", function() {
$(this).remove();
});
};
};
setTimeout(a(), 2000);
};
Edit : I think I understood the problem here :
Because we are talking about closures here, when washAway execution finishes, the variable obj is destroyed so setTimeOut function callback function can't use that resource because it is no more available on the stack and it is not also a global variable.