Administrator
|
How do I rewrite the {...} part of the following in Amber?
$("#MySplitter").splitter({ splitVertical: true, sizeLeft: true }); I naively tried: '#MySplitter' asJQuery splitter: { 'splitVertical' -> true. 'sizeLeft' -> true } but that didn't seem to work...
Cheers,
Sean |
Sean P. DeNigris wrote: > How do I rewrite the {...} part of the following in Amber? > > $("#MySplitter").splitter({ > splitVertical: true, > sizeLeft: true > }); > > I naively tried: > '#MySplitter' asJQuery splitter: { 'splitVertical' -> true. 'sizeLeft' > -> true } It's not naive, Amber has syntax for this, you just must start it with #{ instead of {. {'foo'->'bar'. 'baz'->'quux'} is of course a legal, though different, thing -- an array with two associations (it would be worse if it magically transformed to something else just because all of it's elements are associations -- dynamic array stays dynamic array, for creating 'hash' there is different syntax). It needs to be mentioned, though, that #{...} syntax does not create plain objects, but HashedCollection instances, OTOH, for 99% of cases or more they can be used in place where inline object are used in JS (for example, various jQuery api calls). -- You received this message because you are subscribed to the Google Groups "amber-lang" group. To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email]. For more options, visit https://groups.google.com/d/optout. |
Administrator
|
Thanks! That worked. I added an explanation to the wiki (https://github.com/amber-smalltalk/amber/wiki/From-smalltalk-to-javascript-and-back#creating-objects). Let me know if it's clear: ##JavaScript Objects from Smalltalk ... ###Creating Objects Sometimes you need to create an inline JS object, for example as an argument to this splitter() function: $("#MySplitter").splitter({ splitVertical: true, sizeLeft: true }); In 99% of these cases, you can simulate the object with a HashedCollection like so: { 'splitVertical' -> true. 'sizeLeft' -> true }
Cheers,
Sean |
In reply to this post by Sean P. DeNigris
"Sean P. DeNigris" <[hidden email]>napísal/a: I added an explanation to the wiki (https://github.com/amber-smalltalk/amber/wiki/From-smalltalk-to-javascript-and-back#creating-objects). Let me know if it's clear: ##JavaScript Objects from Smalltalk ... ###Creating Objects Sometimes you need to create an inline JS object, for example as an argument to this splitter() function: $("#MySplitter").splitter({ splitVertical: true, sizeLeft: true }); In 99% of these cases, you can simulate the object with a HashedCollection like so: { 'splitVertical' -> true. 'sizeLeft' -> true } Well, all fine, except the missing # at the beginning. I would include the complete call, to see whole JS and whole ST. -- You received this message because you are subscribed to the Google Groups "amber-lang" group. To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email]. For more options, visit https://groups.google.com/d/optout. |
Administrator
|
Ha ha, I left it out again. Thanks for fixing the wiki.
Cheers,
Sean |
Administrator
|
In reply to this post by Herby Vojčík
In my current project, I tried to port: $('#jstree').jstree({ "plugins" : [ "contextmenu" ] }); as: '#navigation' asJQuery jstree: #{ 'plugins' -> { 'contextmenu' } }. which did not work. There was no error, it just didn't properly initialize the jsTree. I then found http://stackoverflow.com/a/13668585/424245 and ended up with: options := self jsObject. options at: #plugins put: { 'contextmenu' }. '#navigation' asJQuery jstree: options. where: MyClass>>jsObject <return {}> which worked. Did I find the 1% case?
Cheers,
Sean |
Interesting, as there is nothing special with this case on the first look. It's probably something with JSTree treating plugins array somehow strangely. Yes, these cases make that 1%.
BTW, when I really need an empty JS object, I am too lazy to create special method for it. I do `JSON parse: '{}'` ;-) Herby Sean P. DeNigris wrote: > Herby Vojčík wrote >> In 99% of these cases, you can simulate the object with a HashedCollection >> like so: { 'splitVertical' -> true. 'sizeLeft' -> true } > > In my current project, I tried to port: > $('#jstree').jstree({ > "plugins" : [ "contextmenu" ] > }); > as: > '#navigation' asJQuery jstree: #{ 'plugins' -> { 'contextmenu' } }. > which did not work. There was no error, it just didn't properly initialize > the jsTree. > > I then found http://stackoverflow.com/a/13668585/424245 and ended up with: > options := self jsObject. > options at: #plugins put: { 'contextmenu' }. > '#navigation' asJQuery jstree: options. > w > MyClass>>jsObject > <return {}> > which worked. > > Did I find the 1% case? > > > > ----- > Cheers, > Sean > -- > View this message in context: http://forum.world.st/Create-JS-Object-in-Smalltalk-tp4769429p4771047.html > Sent from the Amber Smalltalk mailing list archive at Nabble.com. > -- You received this message because you are subscribed to the Google Groups "amber-lang" group. To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email]. For more options, visit https://groups.google.com/d/optout. |
Administrator
|
There is something very odd going on.
Here's a snippet from my method: install | action menuItem | action := self jsObject at: 'action' put: [ :node | console log: 'do it. do it' ]; yourself. menuItem := self jsObject at: 'create' put: action; yourself. The compiled JS is: fn: function (){ var self=this; var options,action,menuItem,items; ... return smalltalk.withContext(function($ctx1) { var $1,$2,$3,$4,$5,$6,$7; ... $2=self._jsObject(); $ctx1.sendIdx["jsObject"]=1; _st($2)._at_put_("action",(function(node){ return smalltalk.withContext(function($ctx2) { return _st(console)._log_("do it. do it"); }, function($ctx2) {$ctx2.fillBlock({node:node},$ctx1,1)})})); $ctx1.sendIdx["at:put:"]=1; $3=_st($2)._yourself(); $ctx1.sendIdx["yourself"]=1; action=$3; $4=self._jsObject(); $ctx1.sendIdx["jsObject"]=2; _st($4)._at_put_("create",action); $ctx1.sendIdx["at:put:"]=2; $5=_st($4)._yourself(); menuItem=$5; The interesting part is: $3=_st($2)._yourself(); action=$3; $5=_st($4)._yourself(); menuItem=$5; In the first case, the send to #yourself is effectively throw away, where in the second, its result is used. And indeed, if I hand edit from `menuItem=$5;` to `menuItem=$4;`, the code acts as expected. Is this a known bug? I briefly scanned the compiler code and I'm willing to take a crack at it given a pointer in the right direction.
Cheers,
Sean |
Sean P. DeNigris wrote: > There is something very odd going on. > > Here's a snippet from my method: > install > > | action menuItem | > action := self jsObject > at: 'action' put: [ :node | console log: 'do it. do it' ]; > yourself. > menuItem := self jsObject > at: 'create' put: action; > yourself. > > The compiled JS is: > fn: function (){ > var self=this; > var options,action,menuItem,items; > ... > return smalltalk.withContext(function($ctx1) { > var $1,$2,$3,$4,$5,$6,$7; > ... > $2=self._jsObject(); > $ctx1.sendIdx["jsObject"]=1; > _st($2)._at_put_("action",(function(node){ > return smalltalk.withContext(function($ctx2) { > return _st(console)._log_("do it. do it"); > }, function($ctx2) {$ctx2.fillBlock({node:node},$ctx1,1)})})); > $ctx1.sendIdx["at:put:"]=1; > $3=_st($2)._yourself(); > $ctx1.sendIdx["yourself"]=1; > action=$3; > $4=self._jsObject(); > $ctx1.sendIdx["jsObject"]=2; > _st($4)._at_put_("create",action); > $ctx1.sendIdx["at:put:"]=2; > $5=_st > menuItem=$5; > > The interesting part is: > $3=_st($2)._yourself(); > action=$3; > $5=_st($4)._yourself(); > menuItem=$5; > > In the first case, the send to #yourself is effectively throw away, where in > the second, its result is used. And indeed, if I hand edit from > `menuItem=$5;` to `menuItem=$4;`, the code acts as expected. Well, yourself. If you send yourself to JS object, you don't get that JS object (unboxed), but JSObjectProxy instance (boxed). It's the same for any other value which is boxed / unboxed (numbers, strings), though here it is the extreme case, changing actual object to its wrapper. But that's how yourself works - it returns the ST receiver, and in case of JS objects that need wrapping in JSObjectProxy class, it is, alas, the JSObjectProxy instance. You may argue that yourself should return the JS objec t itself, if there would be agreement on that, JSObjectProxy >> yourself can be added. > Is this a known bug? I briefly scanned the compiler code and I'm willing to > take a crack at it given a pointer in the right direction. Again, is there a bug or you just misread $3 as $2 in "action = $3"? > ----- > Cheers, > Sean > -- Herby -- You received this message because you are subscribed to the Google Groups "amber-lang" group. To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email]. For more options, visit https://groups.google.com/d/optout. |
Administrator
|
Okay, I could've sworn is was $2, but I recompiled subsequently and can't go back and check, so let's just chock it up to a misread. But... That explains why the yourself version doesn't work, but I'm still confused as to why the following pattern works: items := self jsObject. "#1" items at: 'items' put: [ :arg | menuItem ]. "#2" options := self jsObject. "#3" options at: 'contextmenu' put: items. "#4" options at: 'plugins' put: { 'contextmenu' }. "#5" '#navigation' asJQuery jstree: options. "#6" where: MyClass>>jsObject <return {}> In lines #1 & #3, aren't I storing the same boxed proxy that would be returned by #yourself? Then in lines #4 and #6, aren't I passing the proxy again? But this time it all works... If I instead us the following pattern, it works, but for more obvious reasons (to me): menuItem := self jsObject at: 'create' put: itemOptions; jsObject. items := self jsObject at: 'items' put: [ :arg | menuItem ]; jsObject. Now I'm explicitly storing and passing around the underlying JS objects. How can this be equivalent to the first example code above? Thanks for walking me through this!
Cheers,
Sean |
Sean P. DeNigris wrote: > Herby Vojčík wrote >> I don't understand, what throwaway? In both cases, result of call to >> ._yourself() is used ($3 is first case, $5 in second case). > > Okay, I could've sworn is was $2, but I recompiled subsequently and can't go > back and check, so let's just chock it up to a misread. > > But... > > Herby Vojčík wrote >> If you send yourself to JS object, you don't get that JS object (unboxed) > > That explains why the yourself version doesn't work, but I'm still confused > as to why the following pattern works: > items := self jsObject. "#1" > items at: 'items' put: [ :arg | menuItem ]. "#2" > options := self jsObject. "#3" > options at: 'contextmenu' put: items. "#4" > options at: 'plugins' put: { 'contextmenu' }. "#5" > '#navigation' asJQuery jstree: options. "#6" > where: > MyClass>>jsObject > <return {}> > > In lines #1& #3, aren't I storing the same boxed proxy that would be > returned by #yourself? Then in lines #4 and #6, aren't I passing the proxy No. The boxing of foo only occurs when foo needs to act as a receiver (receiver _must_ be a Smalltalk object). So, return value of `self jsObject` is indeed that JS object, unboxed. OTOH, if you send #yourself to it, it is boxed not because of yourself, but because of being a receiver. > again? But this time it all works... > > If I instead us the following pattern, it works, but for more obvious > reasons (to me): > menuItem := self jsObject > at: 'create' put: itemOptions; > jsObject. > items := self jsObject > at: 'items' put: [ :arg | menuItem ]; > jsObject. Yes, this works, since you ask boxed JSObjectProxy for its wrapped jsObject (by sending it #jsObject). But that code is, as you surely see, wrong from design reasons, as it's assuming the proxying, which should be transparent from ST code view. As I wrote, one possibility is to come to the conclusion the JSObjectProxy >> yourself should be `^ self jsObject`, which would make the general pattern work well, but there is a consistency problem with the rest of yourselfs, which always return boxed object. In the present state of things, #value is the message that returns unboxed receiver, but it has its own semantic for BlockClosure, so maybe Nico should allow to introduce special receiver for getting the unboxed value. > Now I'm explicitly storing and passing around the underlying JS objects. How > can this be equivalent to the first example code above? > > Thanks for walking me through this! > ----- > Cheers, > Sean > -- Herby -- You received this message because you are subscribed to the Google Groups "amber-lang" group. To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email]. For more options, visit https://groups.google.com/d/optout. |
Administrator
|
Oh, I see now. This is a trap for new users. I think it should be clearly explained somewhere prominent. If the purpose of the proxy is to temporarily wrap the jsObject to send ST messages to it, maybe all its methods should return the jsObject. Then it will be wrapped again if you need to send message to it, right? It may be less efficient, but the current state is confusing - sometimes you get a jsObject, and sometimes a proxy...
Cheers,
Sean |
Administrator
|
In reply to this post by Herby Vojčík
It's just a symptom of the underlying problem. The pattern of requiring: tmp := self jsObject. jsObject doSomething. vs. tmp := self jsObject doSomething; yourself. makes it just as obvious that something unusual is going on as sending #jsObject
Cheers,
Sean |
Sean P. DeNigris wrote: > Herby Vojčík wrote >> But that code is, as you surely see, >> wrong from design reasons, as it's assuming the proxying, which should >> be transparent from ST code view. > > It's just a symptom of the underlying problem. The pattern of requiring: > tmp := self jsObject. > jsObject doSomething. > vs. > tmp := self jsObject > doSomething; > yourself. > makes it just as obvious that something unusual is going on as sending > #jsObject Yes, of course. I am beginning to think yourself should always return unboxed receiver (and special receiver should be dedicated to get boxed one). > ----- > Cheers, > Sean > -- Herby -- You received this message because you are subscribed to the Google Groups "amber-lang" group. To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email]. For more options, visit https://groups.google.com/d/optout. |
Herby Vojčík wrote: > > > Sean P. DeNigris wrote: >> Herby Vojčík wrote >>> But that code is, as you surely see, >>> wrong from design reasons, as it's assuming the proxying, which should >>> be transparent from ST code view. >> >> It's just a symptom of the underlying problem. The pattern of requiring: >> tmp := self jsObject. >> jsObject doSomething. >> vs. >> tmp := self jsObject >> doSomething; >> yourself. >> makes it just as obvious that something unusual is going on as sending >> #jsObject > > Yes, of course. I am beginning to think yourself should always return > unboxed receiver (and special receiver should be dedicated to get boxed > one). > >> ----- >> Cheers, >> Sean >> -- > > Herby > -- You received this message because you are subscribed to the Google Groups "amber-lang" group. To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email]. For more options, visit https://groups.google.com/d/optout. |
In reply to this post by Sean P. DeNigris
or with # instead?
'plugins' -> #{ 'contextmenu' } sebastian o/ > On 30/07/2014, at 19:32, "Sean P. DeNigris" <[hidden email]> wrote: > > 'plugins' -> { 'contextmenu' } -- You received this message because you are subscribed to the Google Groups "amber-lang" group. To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email]. For more options, visit https://groups.google.com/d/optout. |
Administrator
|
No it actually expects an array. I tried unsuccessfully with # first.
Cheers,
Sean |
Free forum by Nabble | Edit this page |