sparks wrote:
Haha, Blob8108, you don't have to try Panther if you don't want to
Hey, I just wanted to see what you'd say to recommend it I'll go try it now, methinks...
Offline
I have an exam in two hours and a sore throat. I don't feel up to recommending anything but a throat lozenge! Plus I forgot my book so the one-and-a-half hour bus journey home today is going to be boring... I'll spend the time thinking about good layouts for the block library site or something
Offline
sparks wrote:
one-and-a-half hour bus journey home
I feel your pain; I have to deal with a one hour to one-and-a-half hour ride, except it's worse for me because I get motion sick if I try to read. Anyway, that's where I do most of my theoretical Scratching, so I guess it isn't exactly time wasted.
Offline
sparks wrote:
Well I passed the Artificial Intelligence exam, so I'm in a pretty good mood
congrats
now it's time for some real-world practice
Offline
Well now that exam is over I have a week till the next one. I'll see if I can get the upload thing working for at least one mod.
I'm still unsure about the form for the Scratch blocks though... do you reckon submitters should just be able to name their own selectors?
Also, if a block has code in more than one browser location, how does that have to be laid out for them?
Offline
sparks wrote:
Well now that exam is over I have a week till the next one. I'll see if I can get the upload thing working for at least one mod.
I'm still unsure about the form for the Scratch blocks though... do you reckon submitters should just be able to name their own selectors?
Also, if a block has code in more than one browser location, how does that have to be laid out for them?
Aren't we trying to go for block files? If that is so, this would be a lot easier, you could have a 'select file to upload' and a tab for the block importer. That way the block importer would take care of the uploading, similar to Scratch. Scratch doesn't have an upload button on the website, Scratch uploads projects itself. I was thinking of a similar approach. So far, I have a code which creates a dialog prompting for username, password, and comment describing the block. It then generates a block file and stores it in a string variable. My idea is for it to then send the username information and the block file as a string. Then the website would generate a block file, ( a plain text file with a '.block' extension). And when a librarian approves the block they would add it to the library. Feel free to add to idea.
Offline
That's a good point. If we go with that approach, though, people will have no choice but to use your mod if they want to share Scratch blocks. Then again, since we're planning on storing them only in the block file format, that's not too bad a thing.
If you wanted to have an export feature in the patch, we would have to work out how to get smalltalk to POST data, since GET won't hold a file as large as these. Maybe the block exporter could (at least for the moment) simply create a block file and save it to a user-selected folder of the user's local drive. They could then click the "browse" button on the upload form and find their file to directly upload it that way?
Are you still planning to release this as a patch as well as an image?
Last edited by sparks (2012-05-15 10:51:47)
Offline
sparks wrote:
That's a good point. If we go with that approach, though, people will have no choice but to use your mod if they want to share Scratch blocks. Then again, since we're planning on storing them only in the block file format, that's not too bad a thing.
If you wanted to have an export feature in the patch, we would have to work out how to get smalltalk to POST data, since GET won't hold a file as large as these. Maybe the block exporter could (at least for the moment) simply create a block file and save it to a user-selected folder of the user's local drive. They could then click the "browse" button on the upload form and find their file to directly upload it that way?
Are you still planning to release this as a patch as well as an image?
Yes. that sounds perfect. I am actually going to start making a patch with additional instructions on how to add on to your own mod.
Offline
I made a patch here () for those who wan to add this to there mod.
Once you file that in I have special instructions.
If you haven't changed the method skip copy it into the respective destination in the browser.
1st: CommandBlockMorph canBecomeWatcher
canBecomeWatcher
| t1 t2 |
NotWatcherBlocks ifNil: [NotWatcherBlocks _ #()].
t2 _ (NotWatcherBlocks includes: selector).
t1 _ selector asString findAnySubStr: #('mouse' 'key' 'touching' 'distance' "add your stuff here") startingAt: 1.
t2 ifTrue: [^ false].
^ self isReporter & (self argumentCount <= 1) & (#(#not #atRandom #abs #rounded #lineCountOfList: #stringLength: "add your stuff here") includes: selector) not & (t1 > selector asString size).
2nd: CommandBlockMorph uncoloredArgMorphsFor:
uncoloredArgMorphFor: t1
| t2 |
t2 _ t1 copyFrom: 2 to: t1 size.
'Attributes' = t2 ifTrue: [^ AttributeArgMorph new choice: 'volume'].
'Boolean' = t2 ifTrue: [^ BooleanArgMorph new].
'Color' = t2 ifTrue: [^ ColorArgMorph new showPalette: true].
'ScreenColor' = t2 ifTrue: [^ ColorArgMorph new showPalette: false].
'Directions' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '0';
menuSelector: #directionMenu].
'Drums' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '48';
menuSelector: #midiDrumMenu].
'Event' = t2 ifTrue: [^ EventTitleMorph new].
'MathFunctions' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #mathFunctionNames;
choice: #sqrt].
'Constants' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #constantNames].
'Effects' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #graphicEffectNames;
choice: #color].
'ColorVar' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new stringExpression: 'a color';
menuSelector: #colorsMenu].
'SensorNames' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #hookupSensorNames].
'SensorBooleans' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #hookupBooleanSensorNames].
'Instruments' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1';
menuSelector: #midiInstrumentMenu].
'ListIndex' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1';
menuSelector: #listIndexMenu].
'Keys' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #keyNames;
choice: 'space'].
'NamedColors' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #namedColors;
choice: #black].
'List' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new stringExpression: 'a list';
menuSelector: #listsMenu].
'Costumes' = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #costumeNames;
choice: 'costume1'].
'Sprite' = t2 ifTrue: [^ SpriteArgMorph new].
'MotorNames' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #motorNames].
'Number' = t2 ifTrue: [^ ExpressionArgMorph new numExpression: '10'].
'Notes' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '60';
menuSelector: #noteSelector].
'String' = t2 ifTrue: [^ ExpressionArgMorph new stringExpression: ''].
'SoundNames' = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #soundNames;
choice: 'pop'].
'TimeDates' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #timeDates;
choice: 'time'].
'LayoutStyles' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #layoutStyles;
choice: 'large'].
'Variable' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new stringExpression: 'a variable';
menuSelector: #varsMenu].
'MotorDirection' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #motorDirection].
'SceneNames' = t2 ifTrue: [^ ChoiceOrExpressionArgMorph new getOptionsSelector: #sceneNames;
choice: ''].
'NewCostume' = t2 ifTrue: [^ ChoiceArgMorph new getOptionsSelector: #newCostumeTypes;
choice: 'camera'].
'ListDelete' = t2 ifTrue: [^ ExpressionArgMorphWithMenu new numExpression: '1';
menuSelector: #listIndexForDeleteMenu].
^ CustomBlockSpecsDictionary customArgs at: t2 asSymbol ifAbsent: [^ ExpressionArgMorph new stringExpression: '']
"what you're going to do here is add your old argmorphs here with words, like such %l = 'List', do you understand what I mean?"
3rd: HatBlockMorph rightButtonMenu
rightButtonMenu
| t1 |
t1 _ CustomMenu new.
t1 add: 'help' action: #presentHelpScreen.
t1 add: 'add to costumes' action: #addToCostumes.
t1 invokeOn: self
"just add your old items to this list before 't1 invokeOn: self'"
4th: ScriptableScratchMorph class blockSpecs:
blockSpecs
| t1 |
t1 _ #('control' ('when $Sprite$ clicked' #S #-) ('when $Keys$ key pressed' #K #-) ('when $Sprite$ clicked' #M #-) #- ('wait $Number$ secs' #t #wait:elapsed:from: 1) #- ('forever' #c #doForever) ('repeat $Number$' #c #doRepeat 10) #- ('broadcast $Event$' #- #broadcast:) ('broadcast $Event $ and wait' #s #doBroadcastAndWait) ('when I receive $Event$' #E #-) #- ('forever if $Boolean$' #c #doForeverIf) ('if $Boolean$' #c #doIf) ('if $Boolean$' #c #doIfElse) ('wait until $Boolean$' #s #doWaitUntil) ('repeat until $Boolean$' #c #doUntil) #- ('stop script' #s #doReturn) ('stop all' #- #stopAll) 'operators' ('$Number$ + $Number$' #r #+ #- #-) ('$Number$ - $Number$' #r #- #- #-) ('$Number$ * $Number$' #r #* #- #-) ('$Number$ / $Number$' #r #/ #- #-) #- ('pick random $Number$ to $Number$' #r #randomFrom:to: 1 10) #- ('$String$ < $String$' #b #< '' '') ('$String$ = $String$' #b #= '' '') ('$String$ > $String$' #b #> '' '') #- ('$Boolean$ and $Boolean$' #b #&) ('$Boolean$ or $Boolean$' #b #|) ('not $Boolean$' #b #not) #- ('join $String$ $String$' #r #concatenate:with: 'hello ' 'world') ('letter $Number$ of $String$' #r #letter:of: 1 'world') ('length of $String$' #r #stringLength: 'world') #- ('$Number$ mod $Number$' #r # #- #-) ('round $Number$' #r #rounded #-) #- ('$MathFunctions$ of $Number$' #r #computeFunction:of: 'sqrt' 10) 'sound' ('play sound $SoundNames$' #- #playSound:) ('play sound $SoundNames$ until done' #s #doPlaySoundAndWait) ('stop all sounds' #- #stopAllSounds) #- ('play drum $Drums$ for $Number$ beats' #t #drum:duration:elapsed:from: 48 0.2) ('rest for $Number$ beats' #t #rest:elapsed:from: 0.2) #- ('play note $Notes$ for $Number$ beats' #t #noteOn:duration:elapsed:from: 60 0.5) ('set instrument to $Instruments$' #- midiInstrument: 1) #- ('change volume by $Number$' #- #changeVolumeBy: -10) ('set volume to $Number$%' #- #setVolumeTo: 100) ('volume' #r #volume) #- ('change tempo by $Number$' #- #changeTempoBy: 20) ('set tempo to $Number$ bpm' #- #setTempoTo: 60) ('tempo' #r #tempo) 'motor' ('motor on for $Number$ secs' #t #motorOnFor:elapsed:from: 1) ('motor on' #- #allMotorsOn) ('motor off' #- #allMotorsOff) ('motor power $Number$' #- #startMotorPower: 100) ('motor direction $MotorDirection$' #- #setMotorDirection: 'this way') 'variables' ('show variable $Variable$' #- #showVariable:) ('hide variable $Variable$' #- #hideVariable:) 'list' ('add $String$ to $List$' #- #append:toList: 'thing') #- ('delete $ListDelete$ of $List$' #- #deleteLine:ofList: 1) ('insert $String$ at $ListIndex$ of $List$' #- #insert:at:ofList: 'thing' 1) ('replace item $ListIndex$ of $List$ with $String$' #- #setLine:ofList:to: 1 'list' 'thing') #- ('item $ListIndex$ of $List$' #r #getLine:ofList: 1) ('length of $List$' #r #lineCountOfList:) ('$List$ contains $String$' #b #list:contains: 'list' 'thing') ).
^ t1 , self obsoleteBlockSpecs , (CustomBlockSpecsDictionary formatAsArrayFor: 'All')
"add all your blocks here as well and to the same to the following block specs"
4th ScratchSpriteMorph class blockSpecs
blockSpecs
| t1 |
t1 _ #('motion' ('move $Number$ steps' #- #forward:) ('turn $Number$ degrees' #- #turnRight: 15) ('turn $Number$ degrees' #- #turnLeft: 15) #- ('point in direction $Directions$' #- #heading: 90) ('point towards $Sprite$' #- #pointTowards:) #- ('go to x:$Number$ y:$Number$' #- #gotoX:y: 0 0) ('go to $Sprite$' #- #gotoSpriteOrMouse:) ('glide $Number$ secs to x:$Number$ y:$Number$' #t #glideSecs:toX:y:elapsed:from: 1 50 50) #- ('change x by $Number$' #- #changeXposBy: 10) ('set x to $Number$' #- #xpos: 0) ('change y by $Number$' #- #changeYposBy: 10) ('set y to $Number$' #- #ypos: 0) #- ('if on edge, bounce' #- #bounceOffEdge) #- ('x position' #r #xpos) ('y position' #r #ypos) ('direction' #r #heading) 'pen' ('clear' #- #clearPenTrails) #- ('pen down' #- #putPenDown) ('pen up' #- #putPenUp) #- ('set pen color to $Color$' #- #penColor:) ('change pen color by $Number$' #- #changePenHueBy:) ('set pen color to $Number$' #- #setPenHueTo: 0) #- ('change pen shade by $Number$' #- #changePenShadeBy:) ('set pen shade to $Number$' #- #setPenShadeTo: 50) #- ('change pen size by $Number$' #- #changePenSizeBy: 1) ('set pen size to $Number$' #- #penSize: 1) #- ('stamp' #- #stampCostume) ).
t1 _ t1 , #('looks' ('switch to costume $Costumes$' #- #lookLike:) ('next costume' #- #nextCostume) ('costume #' #r #costumeIndex) #- ('say $String$ for $Number$ secs' #t #say:duration:elapsed:from: 'Hello!' 2) ('say $String$' #- #say: 'Hello!') ('think $String$ for $Number$ secs' #t #think:duration:elapsed:from: 'Hmm...' 2) ('think $String$' #- #think: 'Hmm...') #- ('change $Effects$ effect by $Number$' #- #changeGraphicEffect:by: 'color' 25) ('set $Effects$ effect to $Number$' #- #setGraphicEffect:to: 'color' 0) ('clear graphic effects' #- #filterReset) #- ('change size by $Number$' #- #changeSizeBy:) ('set size to $Number$%' #- #setSizeTo: 100) ('size' #r #scale) #- ('show' #- #show) ('hide' #- #hide) #- ('go to front' #- #comeToFront) ('go back $Number$ layers' #- #goBackByLayers: 1) 'sensing' ('touching $Sprite$?' #b #touching:) ('touching color $ScreenColor$?' #b #touchingColor:) ('color $ScreenColor$ is touching $ScreenColor$?' #b #color:sees:) #- ('ask $String$ and wait' #s #doAsk 'What''s your name?') ('answer' #r #answer) #- ('mouse x' #r #mouseX) ('mouse y' #r #mouseY) ('mouse down?' #b #mousePressed) #- ('key $Keys$ pressed?' #b #keyPressed: 'space') #- ('distance to $Sprite$' #r #distanceTo:) #- ('reset timer' #- #timerReset) ('timer' #r #timer) #- ('$Attributes$ of $Sprite$' #r #getAttribute:of:) #- ('loudness' #r #soundLevel) ('loud?' #b #isLoud) #~ ('$SensorBooleans$ sensor value' #r #sensor: 'slider') ('sensor $SensorNames$?' #b #sensorPressed: 'button pressed') ).
"see ScriptableScratchMorph blockSpecs"
^ t1 , super blockSpecs , (CustomBlockSpecsDictionary formatAsArrayFor: 'Sprites')
5th: ScratchStageMorph blockSpecs
blockSpecs
| t1 |
t1 _ #('sensing' ('ask $String$ and wait' #s #doAsk 'What''s your name?') ('answer' #r #answer) #- ('mouse x' #r #mouseX) ('mouse y' #r #mouseY) ('mouse down?' #b #mousePressed) #- ('key $Keys$ pressed?' #b #keyPressed: 'space') #- ('reset timer' #- #timerReset) ('timer' #r #timer) #- ('$Attributes$ of $Sprite$' #r #getAttribute:of:) #- ('loudness' #r #soundLevel) ('loud?' #b #isLoud) #~ ('$SensorBooleans$ sensor value' #r #sensor: 'slider') ('sensor $SensorNames$?' #b #sensorPressed: 'button pressed') 'looks' ('switch to background $Costumes$' #- #showBackground: 'background1') ('next background' #- #nextBackground) ('background #' #r #backgroundIndex) #- ('change $Effects$ effect by $Number$' #- #changeGraphicEffect:by: 'color' 25) ('set $Effects$ effect to $Number$' #- #setGraphicEffect:to: 'color' 0) ('clear graphic effects' #- #filterReset) #- 'pen' ('clear' #- #clearPenTrails) ).
^ t1 , super blockSpecs , (CustomBlockSpecsDictionary formatAsArrayFor: 'Stage')
"see ScriptableScratchMorph class blockSpecs"
6th: ScriptableScratchMorph defaultArgs:
defaultArgsFor: t1
| t2 t3 t4 t5 t6 |
t2 _ t1 copyFrom: 4 to: t1 size.
t3 _ self ownerThatIsA: ScratchStageMorph.
t4 _ (t1 at: 3) asSymbol.
#gotoX:y: = t4 ifTrue: [t2 _ Array with: self referencePosition x rounded with: self referencePosition y rounded].
#glideSecs:toX:y:elapsed:from: = t4 ifTrue: [t2 _ Array
with: 1
with: self referencePosition x rounded
with: self referencePosition y rounded].
#motor:direction: = self ifTrue: [t2 _ Array
with: 'reverse' localized
with: 'this way' localized
with: 'that way'].
#setSizeTo: = t4
ifTrue:
[t5 _ (100.0 * (self scalePoint x max: self scalePoint y) ) rounded.
t2 _ Array with: t5].
#getAttribute:of: = t4 ifTrue: [(t3 _ self ownerThatIsA: ScratchStageMorph) ifNil: [t2 _ Array with: 'x position' with: self]
ifNotNil:
[t6 _ t3 submorphs select: [:t7 | t7 isKindOf: ScratchSpriteMorph].
t6 sort: [:t8 :t9 | t8 objName asLowercase < t9 objName asLowercase].
t6 size > 0
ifTrue: [t2 _ Array with: 'x position' with: t6 first]
ifFalse: [t2 _ Array with: 'background #' with: t3]]].
#concatenate:with: = t4 ifTrue: [t2 _ Array with: 'hello ' localized with: 'world' localized].
#doAsk = t4 ifTrue: [t2 _ Array with: 'What''s your name?' localized].
#letter:of: = t4 ifTrue: [t2 _ Array with: 1 with: 'world' localized].
#stringLength: = t4 ifTrue: [t2 _ Array with: 'world' localized].
#say:duration:elapsed:from: = t4 ifTrue: [t2 _ Array with: 'Hello!' localized with: 2].
#say: = t4 ifTrue: [t2 _ Array with: 'Hello!' localized].
#think:duration:elapsed:from: = t4 ifTrue: [t2 _ Array with: 'Hmm...' localized with: 2].
#think: = t4 ifTrue: [t2 _ Array with: 'Hmm...' localized].
(#(#lookLike: #showBackground: ) includes: t4)
ifTrue: [t2 _ Array with: self costumeNames last].
(#(#playSound: #doPlaySoundAndWait ) includes: t4)
ifTrue:
[t6 _ self soundNames.
t2 _ t6 size <= 2
ifTrue: [Array with: '']
ifFalse: [Array with: (t6 at: t6 size - 2)]].
(#(#broadcast: #doBroadcastAndWait ) includes: t4)
ifTrue: [t3 ifNotNil: [t2 _ Array with: t3 defaultEventName]].
(#(#append:toList: #deleteLine:ofList: #insert:at:ofList: ) includes: t4)
ifTrue: [t2 size >= 1 ifTrue: [t2 at: 1 put: (t2 at: 1) localized]].
(#(#append:toList: #deleteLine:ofList: #getLine:ofList: #insert:at:ofList: #lineCountOfList: ) includes: t4)
ifTrue: [t2 _ t2 copyWith: self defaultListName].
#setLine:ofList:to: = t4
ifTrue: [t2 size >= 3
ifTrue:
[t2 at: 2 put: self defaultListName.
t2 at: 3 put: (t2 at: 3) localized]].
#appendLettersOf:toList: = t4
ifTrue: [t2 size >= 2
ifTrue:
[t2 at: 1 put: (t2 at: 1) localized.
t2 at: 2 put: self defaultListName]].
#list:contains: = t4
ifTrue: [t2 size >= 2
ifTrue:
[t2 at: 1 put: self defaultListName.
t2 at: 2 put: (t2 at: 2) localized]].
#selector = t4
ifTrue: [t2 size >= 1 ifTrue: [t2 at: 1 put: 'hello world' localized]].
#selector = sel
ifTrue: [defaultArgs size >= 1 ifTrue: [defaultArgs at: 1 put: 'hello world' localized]]. ^ t2
"add your default args here"
7th: ScratchFrameMorph createMenuPanel
createMenuPanel
| t1 t2 |
menuPanel _ AlignmentMorph new color: Color transparent;
centering: #center;
inset: 0;
height: 0.
self addShortcutButtonsTo: menuPanel.
t1 _ #( (#File #fileMenu:) (#Edit #editMenu:) (#Blocks #blocksMenu:) "add your panels here"(#Help #helpMenu:) (#Dev #devMenu:) ).
t1 do:
[:t3 |
t2 _ ScratchMenuTitleMorph new contents: (t3 at: 1) localized;
target: self selector: (t3 at: 2).
menuPanel addMorphBack: t2.
#devMenu: = (t3 at: 2) ifFalse: [menuPanel addMorphBack: (Morph new color: Color transparent;
extent: 12 @ 5)]].
topPane addMorph: menuPanel
Offline
Sparks, I was searching in the squeak browser (scratch source code) and found a method named: "httpPostDocument: url args: argsDict accept: mimeType request: requestString" in HTTPSocket class. Here is the first comment in the method: "like httpGET, except it does a POST instead of a GET. POST allows data to be uploaded" This might be the method I'm looking for.
Offline
dreamod wrote:
Sparks, I was searching in the squeak browser (scratch source code) and found a method named: "httpPostDocument: url args: argsDict accept: mimeType request: requestString" in HTTPSocket class. Here is the first comment in the method: "like httpGET, except it does a POST instead of a GET. POST allows data to be uploaded" This might be the method I'm looking for.
I looked at this before, and I think you can't use that method for uploading blocks. I can't remember why, though
I think it's better to implement your own HTTP protocol — at least, that's what the Scratch team did for uploading projects, I think. I could give advice on that if you so wish
Last edited by blob8108 (2012-05-15 13:18:50)
Offline
blob8108 wrote:
dreamod wrote:
Sparks, I was searching in the squeak browser (scratch source code) and found a method named: "httpPostDocument: url args: argsDict accept: mimeType request: requestString" in HTTPSocket class. Here is the first comment in the method: "like httpGET, except it does a POST instead of a GET. POST allows data to be uploaded" This might be the method I'm looking for.
I looked at this before, and I think you can't use that method for uploading blocks. I can't remember why, though
I think it's better to implement your own HTTP protocol — at least, that's what the Scratch team did for uploading projects, I think. I could give advice on that if you so wish
Why shouldn't I use the method? Sparks recommended that I use POST to send it. I think I'll at least test it.
Offline
Well you're welcome to, but it will need a PHP script up at the other end of the transfer. If you tell me the names of each variable you are passing, I can set up a response page.
In the meantime, I've set up www.blocks.scratchr.org/postPing.php which will echo back any POST data that it is sent. If it pings "Array ( ) " then that means it hasn't found any post data, as will happen if you just click that link. If your variable names and values are returned, then you've sent them successfully.
If anyone wants the code:
<?php //postPing.php //function: pings POST data sent to it print_r($_POST); ?>
Offline
For example, I hacked the comment space on this forum to send the data to that page instead of the post page on the Scratch site and the page pinged:
Array ( [form_sent] => 1 [form_user] => sparks [req_message] => test )
Offline
sparks wrote:
For sending POST data? I don't know either
For httpPostDocument:args:, it appears the first arg is a String containing the URL and the second is a collection of some sort...the objects of the collection appear to need a "value" method which returns an object with a do: [ ] method.
Offline
Greenatic wrote:
sparks wrote:
For sending POST data? I don't know either
For httpPostDocument:args:, it appears the first arg is a String containing the URL and the second is a collection of some sort...the objects of the collection appear to need a "value" method which returns an object with a do: [ ] method.
I think I got that part, but I really need this to work. If I do then I can easily finish the final version.
Offline