I'm trying to use some node.js modules in a chrome packaged app. (I'm talking to the serial port)
I've extended the Buffer prototype to add the 'indexOf' method.
I'm using Browserify, and what seems to be happening is it doesn't pick up my prototype extension. My Buffers end up being Uint8Arrays without indexOf available.
Is there a trick to extending Buffer in a way that Browserify will pick up?
My extension looks like this, but I've also tried npm packages that do the same thing (the below code was lifted from one), so I think the problem isn't necessarily in my code:
Buffer.indexOf = function(haystack, needle, i) {
if (!Buffer.isBuffer(needle)) {
needle = new Buffer(needle);
}
if (typeof i === 'undefined') {
i = 0;
}
var l = haystack.length - needle.length + 1;
while (i < l) {
var good = true;
for (var j = 0, n = needle.length; j < n; j++) {
if (haystack.get(i + j) !== needle.get(j)) {
good = false;
break;
}
}
if (good) {
return i;
}
i++;
}
return -1;
};
Buffer.prototype.indexOf = function(needle, i) {
return Buffer.indexOf(this, needle, i);
}
Is there a trick to extending Buffer in a way that Browserify will pick up?
I doubt it, since browserify has its own implementation for Buffer.
But what's worse is that any other module that uses your module is affected by your change to Buffer.prototype. Instead of extending the prototype of a core component, you should create a helper function instead.
Related
I am trying to implement generators in Node.js. I came across node-fiber and node-lazy. Node-lazy deals with arrays and streams, but does not generate lazy things inherently (except numbers).
While using fiber looks cleaner, it has its cons, and as such, I prefer pure Javascript with closures as it's more explicit. My question is: are there memory or perf problems using closure to generate an iterator?
As an example, I'm trying to iterate through a tree depth-first, for as long as the caller asks for it. I want to find 'waldo' and stop at the first instance.
Fiber:
var depthFirst = Fiber(function iterate(tree) {
tree.children.forEach(iterate);
Fiber.yield(tree.value);
});
var tree = ...;
depthFirst.run(tree);
while (true) {
if (depthFirst.run() === 'waldo')
console.log('Found waldo');
}
Pure JavaScript with closures:
function iterate(tree) {
var childIndex = 0;
var childIter = null;
var returned = false;
return function() {
if (!childIter && childIndex < tree.children.length)
childIter = iterate(tree.children[childIndex++]);
var result = null;
if (childIter && (result = childIter()))
return result;
if (!returned) {
returned = true;
return tree.value;
}
};
}
var tree = ...;
var iter = iterate(tree);
while (true) {
if (iter() === 'waldo')
console.log('found waldo');
}
Hi can some one please tell me how to copy one data store to another in dojo. I tried it in following way but it doesn't work. Here I'm try to copy data from jsonStore to newGridStore.
jsonStore.fetch({query:{} , onComplete: onComplete});
var onComplete = function (items, request) {
newGridStore = null;
newGridStore = new dojo.data.ItemFileWriteStore({
data : {}
});
if (items && items.length > 0) {
var i;
for (i = 0; i < items.length; i++) {
var item = items[i];
var attributes = jsonStore.getAttributes(item);
if (attributes && attributes.length > 0) {
var j;
for (j = 0; j < attributes.length; j++) {
var newItem = {};
var values = jsonStore.getValues(item, attributes[j]);
if (values) {
if (values.length > 1) {
// Create a copy.
newItem[attributes[j]] = values.slice(0, values.length);
} else {
newItem[attributes[j]] = values[0];
}
}
}
newGridStore.newItem(newItem);
}
}
}
}
Based on the comments asked above. You are trying to copy values to a new Store for the single reason to be able to detect which values have changes and then save them individually, without having to send the entire store.
This approach is totally wrong.
Dojo has isDirty() and offers you the ability to revert() a store back to it's original values. It knows which values have changed and you don't need to do this.
Take a look at the bog standard IFWS here: http://docs.dojocampus.org/dojo/data/ItemFileWriteStore
Make sure you read everything from here: http://docs.dojocampus.org/dojo/data/ItemFileWriteStore#id8
What you want to do is create your own _saveCustom method which you will override your store with, and then when you save, you will be able to see which values have changed.
Click on the demo at the very bottom of the page. It shows you EXACTLY how do to it using _saveCustom
I have a js function that is named getID which is basically return document.getElementById(id)
I want to make another function, getTag that would return getElementsByTagName.
The part that I can't seem to manage is that I want to be able to call them like this:
getID('myid').getTag('input') => so this would return all the input elements inside the element with the id myid
Thanks!
ps: getTag would also have to work if it's called by it's own, but then it would just return document.getElementsByTagName
UPDATE:
Thanks to all that have replied! Using your suggestions I came up with this, which works well for me:
function getEl(){
return new getElement();
}
function getElement() {
var scope = document;
this.by = function(data){
if (data.id) scope = scope.getElementById(data.id);
if (data.tag) scope = scope.getElementsByTagName(data.tag);
return scope;
}
}
and I use it like this:
var inputs = getEl().by({id:"msg", tag:"input"});
The way to do that is to prototype Object. To do that, you'll need the following piece of code:
Object.prototype.getTag = function(tagName) {
return this.getElementsByTagName(tagName);
}
However, this will expand all objects because what you really need to prototype, an HTMLElement, is very hard to do consistently. All the experts agree that you should never expand the Object prototype. A much better solution would be to create a function that gets the tag name from another argument:
function getTag(tagName, element) {
return (element || document).getElementsByTagName(tagName);
}
// Usage
var oneTag = getTag('input', getID('myid')); // All inputs tags from within the myid element
var twoTag = getTag('input'); // All inputs on the page
This would require that whatever is returned by getID('myid') (an HTML element) exposes a method named getTag(). This is not the case. Browsers implement the DOM specification and expose the methods defined there.
While you technically can enhance native objects with your own methods, it's best not to do it.
What you try to do has been solved rather nicely in JS libraries like jQuery already, I recommend you look at one of them before you invest time in mimicking what they can do. For example, your line of code would become:
$("#myid input")
in jQuery. jQuery happens to be the most widely used JS library around, there are many others.
Basically, you're going to create a single object that contains each of your methods and also stores all data returned by the native functions. It would look something like this (not tested, but you get the idea):
var MyLib = {
getID: function(id) {
var element = document.getElementById(id);
this.length = 1;
this[0] = element;
return this;
},
getTag: function(tag) {
var elements;
if (this.length) {
for (var i = 0; i < this.length; i++) {
var byTag = this[i].getElementsByTagName(tag);
for (var j = 0; j < byTag.length; j++) {
elements.push(byTag[j]);
}
}
}
for (var i = 0; i < elements.length; i++) {
this[i] = elements[i];
}
this.length = elements.length;
return this;
}
};
You can then use it like this:
var elements = MyLib.getID('myid').getTag('input');
for (var i = 0; i < elements.length; i++)
console.log(elements[i]); // Do something
The only real problem with this approach (besides it being very tricky and hard to debug) is that you have to treat the result of every method like an array, even if there is only a single result. For example, to get an element by ID, you'd have to do MyLib.getID('myid')[0].
However, note that this has already been done before. I recommend you take a look at jQuery, if only to see how they accomplished this. Your code could be simplified to this:
$("#myid input")
jQuery is more lightweight than you think, and including it on your page will not slow it down. You have nothing to lose by using it.
Just use the DOMElement.prototype property.
You'll get something like this :
function getTag(tagName) {
return document.getElementsByTagName(tagName);
}
DOMElement.prototype.getTag = function(tagName) {
return this.getElementsByTagName(tagName);
}
But you should use jQuery for this.
EDIT: My solution doesn't work on IE, sorry !
You could define it as follows:
var Result = function(el)
{
this.Element = el;
};
Result.prototype.getTag = function(tagName)
{
return this.Element.getElementsByTagName(tagName);
};
var getTag = function(tagName)
{
return document.getElementsByTagName(tagName);
};
var getID = function(id)
{
var el = document.getElementById(id);
return new Result(el);
};
Whereby a call to getID will return an instance of Result, you can then use its Element property to access the HTML element returned. The Result object has a method called getTag which will return all child elements matching that tag from the parent result. We then also define a seperate getTag method which calls the document element's getElementsByTagName.
Still though...JQuery is so much easier... $("#myId input");
Unless this is an academic exercise on how to chain methods in JavaScript (it doesn't seem to be, you simply seem to be learning JavaScript), all you have to do is this:
var elements = document.getElementById("someIdName");
var elementsByTag = elements.getElementsByTagName("someTagName");
for (i=0; i< elementsByTag.length; i++) {
alert('found an element');
}
If you want to define a reusable function all you have to do is this:
function myFunction(idName,tagName) {
var elements = document.getElementById(idName);
var elementsByTag = elements.getElementsByTagName(tagName);
for (i=0; i< elementsByTag.length; i++) {
alert('found a ' + tagName + ' element within element of id ' + idName);
}
}
It's true that if this is all the JavaScript functionality you need on your page, then there is no need to import jQuery.
In the Javascript for a Firefox extension, you can call gBrowser.getBrowserForTab but there is no gBrowser.getTabForBrowser. So I wrote my own and it works, and I'm just curious if there's any reason I shouldn't be doing this, or if there's anything wrong with the code. The following is in my init method that gets called when the window loads.
gBrowser.getTabForBrowser = function(browser) {
for (var i=0; i<gBrowser.browsers.length; i++) {
if (gBrowser.getBrowserAtIndex(i) === browser) {
return gBrowser.tabContainer.getItemAtIndex(i);
}
}
return null;
}
(or should it be gBrowser.prototype.getTabForBrowser = ...?)
Far as I know there is no built in getTabForBrowser function, so you would have to roll your own. However, your code assumes that browser nodes are stored in the same DOM order as tab nodes. I can't say for sure if this assumption is ever broken, but considering tabs can be re-positioned by the user arbitrarily, it is not something I'd rely on.
Fortunately, each tab object has a linkedBrowser property. So you could rewrite your code like so:
gBrowser.getTabForBrowser = function(browser) {
var mTabs = gBrowser.mTabContainer.childNodes;
for (var i=0, i<mTabs.length; i++) {
if (mTabs[i].linkedBrowser == browser) {
return mTabs[i];
}
}
return null;
}
what would be the best way to implement kind of cheat codes in general?
I have WinForms application in mind, where a cheat code would unlock an easter egg, but the implementation details are not relevant.
The best approach that comes to my mind is to keep index for each code - let's consider famous DOOM codes - IDDQD and IDKFA, in a fictional C# app.
string[] CheatCodes = { "IDDQD", "IDKFA"};
int[] CheatIndexes = { 0, 0 };
const int CHEAT_COUNT = 2;
void KeyPress(char c)
{
for (int i = 0; i < CHEAT_COUNT; i++) //for each cheat code
{
if (CheatCodes[i][CheatIndexes[i]] == c)
{ //we have hit the next key in sequence
if (++CheatIndexes[i] == CheatCodes[i].Length) //are we in the end?
{
//Do cheat work
MessageBox.Show(CheatCodes[i]);
//reset cheat index so we can enter it next time
CheatIndexes[i] = 0;
}
}
else //mistyped, reset cheat index
CheatIndexes[i] = 0;
}
}
Is this the right way to do it?
Edit: Probably the worst thing I should have done was to include the first cheat codes that came from the top of my head as an example. I really did not want to see Doom's source code or their implementation, but general solution to this problem.
Why not download the DOOM source and see for yourself? =)
http://www.doomworld.com/idgames/?id=14576
I think this one's a bit easier to understand, though your original will probably perform better than this one:
using System.Collections.Generic;
void KeyPress(char c)
{
string[] cheatCodes = { "IDDQD", "IDKFA"};
static Queue<char> buffer; //Contains the longest number of characters needed
buffer.Enqueue(c);
if (buffer.Count() > 5) //Replace 5 with whatever your longest cheat code is
buffer.Dequeue();
bufferString = new System.String(buffer.ToArray());
foreach(string code in cheatCodes) {
if (bufferString.EndsWith(code)) {
//Do cheat work
}
}
}
here is the DOOM cheat implementation from the doom source:
#define SCRAMBLE(a) \
((((a)&1)<<7) + (((a)&2)<<5) + ((a)&4) + (((a)&8)<<1) \
+ (((a)&16)>>1) + ((a)&32) + (((a)&64)>>5) + (((a)&128)>>7))
int cht_CheckCheat ( cheatseq_t* cht, char key )
{
int i;
int rc = 0;
if (firsttime)
{
firsttime = 0;
for (i=0;i<256;i++) cheat_xlate_table[i] = SCRAMBLE(i);
}
if (!cht->p)
cht->p = cht->sequence; // initialize if first time
if (*cht->p == 0)
*(cht->p++) = key;
else if
(cheat_xlate_table[(unsigned char)key] == *cht->p) cht->p++;
else
cht->p = cht->sequence;
if (*cht->p == 1)
cht->p++;
else if (*cht->p == 0xff) // end of sequence character
{
cht->p = cht->sequence;
rc = 1;
}
return rc;
}