Server side rendering with Riot.js: Passing opts.foo to this.foo in tag - riot.js

I am having problems with server side rending using Riot.
In my handler, I pass my foo object into my bar tag with something very similar to this:
reply(riot.render(bar, { foo: foo }));
This is a copy of my simple bar tag:
<bar>
<h1>TEST</h1>
<h1>{ foo }</h1>
this.foo = opts.foo
console.log(this.foo)
</bar>
When I point my browser to the relevant path, 'TEST' is visible but foo is not. My console.log(foo) works just fine.

This worked for me on a similar setup
<bar>
<h1>TEST</h1>
<h1>{ opts.foo }</h1>
console.log(opts.foo)
</bar>
I believe it works best to bind directly to the data object instead of setting it to another local variable

Related

Vue3 quick access printing Target in a "Proxy" object

Vue3 prints everthing as an a "Proxy" object.
I know the value is inside [[Target]], but I don't want to keep expading Proxy->[[Target]] every single time.
Just wanted to let clear, this does't change the output at all. it is just a 'cleaner' way to see stuff.
An example:
const b = 'value'
console.log(value)
Output -> { Proxy: { [[Handler]]: ..., [[Target]]: 'value', [[IsRevoked]]: false }
okay, this works.
console.log(JSON.parse(JSON.stringify(b))).
for more info.
Accessing a Proxy object in Vue3

How to change contents of a virtual dom element in Mithril?

How do I access a virtual dom element to change its contents using Mithril? I am new to Mithril and still trying to figure things out. For example, I want to access the third div with id "three" and change it's contents to "Blue Jays" without touching any of the other div's.
Thanks.
<div id='main'>
<div id='one'>Yankees</div><br>
<div id='two'>Red Sox</div><br>
<div id='three'>Orioles</div>
</div>
In mithril, like in react/vue/angular, you dont act on the actual DOM directly. Instead, you define the outcome that you want, so for example, to render the DOM tree that you posted you would do something like this:
var my_view = {
view: vnode => m('div#main', [
m('div#one', 'Yankees'),
m('div#two', 'Red Sox'),
m('div#three', 'Orioles')
])
}
m.mount(root, my_view)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/2.0.4/mithril.js"></script>
<div id="root"></div>
the m(...) functions inside the array have a string as their second argument, that makes the output static, but we can change that to a variable:
var my_view = {
oninit: vnode => vnode.state.fave_team = 'Orioles',
view: vnode => m('div#main', [
m('div#one', 'Yankees'),
m('div#two', 'Red Sox'),
m('div#three', vnode.state.fave_team)
])
}
m.mount(root, my_view)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/2.0.4/mithril.js"></script>
<div id="root">
</div>
In this case I used the state property of the vnode argument, but you can also use a third party state manager like flux or any other.
Now that we have it as a variable, it will show the current value on every call m.redraw(), most of the times we dont have to do this call ourselves, for example:
var my_view = {
oninit: vnode => {
vnode.state.fave_team = 'Orioles'
},
view: vnode => m('div#main', [
m('div#one', 'Yankees'),
m('div#two', 'Red Sox'),
m('div#three', vnode.state.fave_team),
m('button', { onclick: () => vnode.state.fave_team = 'Dodgers' }, 'Change')
])
}
m.mount(root, my_view)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/2.0.4/mithril.js"></script>
<div id="root"></div>
And thats it, any dynamic content in your DOM elements you set it as a variable/property in an object.
One of the beautiful things about mithril is that it doesnt force you to do things one specific way, so if you really want to work on the actual DOM node, there are lifecycle events that you can attach to any virtual node ("vnode")
You can easily capture the HTMLElement (i.e., HTMLInputElement) with the Mithril Lifecycle event of oncreate(). This is an actual example from my code (in TypeScript) where I need to hook up a few event listneres after the canvas element was created and its underlying DOM is available to me at "raw" HTML level. Once you get a hold of dom, then I manipulate that element directly. Many people think that why not use oninit(), but oninit() is before the generation of dom, so you will not get the element back at that stage.
Now, if you just do that, you will likely be posting another question - "Why the browser views not updating?" And that's because you do have to manually do a m.redraw() in your event handlers. Otherwise Mithril would not know when the view diffs to be computed.
const canvas = m(`.row[tabIndex=${my.tabIndex}]`, {
oncreate: (element: VnodeDOM<any, any>) => {
const dom = element.dom;
dom.addEventListener("wheel", my.eventWheel, false);
dom.addEventListener("keydown", my.eventKeyDown, false);
}
},

How can I hide a dijit/form/button?

I think it is a common sense that providing a simple way to hide/show and enable/disable a button, but I cannot find any document that describe dojo has done such thing.
Any way, I hope it is my fault that I have missed out something while googling, thanks!
The following coding is what I have tried but they just make the button's text invisible:
dojo.style(btnInsert, {'visibility':'hidden'});
dojo.style(btnInsert, {'display':'none'});
UPDATE Question:
To oborden2:
I have tried your code, the result is same as the above code, here is the captured screen:
To MiBrock:
I have also tried your code and also get the result that same as the above code:
Form widgets in Dijit are special. For all normal Dijit widgets, the domNode (outermost node) of the widget receives the id property. However, with form widgets, the focusNode (which corresponds to the <input> element) receives the ID instead, so that things like <label for="foo"> work properly. In this case, the outermost node has no ID, and you’re actually just hiding the inner HTML input element.
If you already have reference to the widget:
require([ 'dojo/dom-style' ], function (domStyle) {
domStyle.set(widget.domNode, 'display', 'none');
});
If you only have a reference to the ID of the widget/original DOM node:
require([ 'dojo/dom-style', 'dijit/registry' ], function (domStyle, registry) {
domStyle.set(registry.byId(nodeId).domNode, 'display', 'none');
});
Try
require(["dojo/dom-style","dojo/domReady!"], function(domStyle){
domStyle.set(dojo.byId(domNode),'display','none');
});
The variable "domNode" stays for the id of the Node that should be influenced. This is the way we make it.
Regards, Miriam
Try using the Toggler module
require(["dojo/fx/Toggler"], function(Toggler),{
// Create a new Toggler with default options
var toggler = new Toggler({
node: "btnInsert"
});
// Hide the node
toggler.hide();
// Show the node
toggler.show();
});
http://dojotoolkit.org/reference-guide/1.9/dojo/fx/Toggler.html
I imagine you would want to link this to some event using Dojo's on module. Link it up to whatever condition triggers the button's need to be hidden.

using dijit.byId w dojox.mobile widgets

I'm dynamically building a series of dojox.mobile.ListItem widgets under a statically defined dojox.mobile.RoundRectList widget via this function...
function displayOpps(items) {
// Create the list container that will hold application names
var rrlOppsContainer = dijit.byId("rrlOpps");
// Add a new item to the list container for each element in the server respond
for (var i in items){
// Create and populate the list container with applications' names
var name = items[i].CustName + " - " + items[i].OppNbr;
var liOpps = new dojox.mobile.ListItem({
label: name,
moveTo: "sv3OppDetail"
});
// Add the newly created item to the list container
rrlOppsContainer.addChild(liOpps);
}
}
When I run this code during onLoad() in my html file, I get the following error using Chrome's dev tools...
Uncaught TypeError: Object # has no method 'byId'
I've read numerous articles around this topic and it appears that lots of folks have this problem, but each that I have found are in relation to some other technology (e.g., Spring MVC, etc) and I'm attempting to use it w a dojox.mobile based app. That said, I attempted to mimic some of the solutions brought up by others by including this in my html file, and it still doesn't work...
<script type="text/javascript"
data-dojo-config="isDebug: true, async: true, parseOnLoad: true"
src="dojo/dojo.js">
dojo.require("dojox.mobile.RoundRectList")
</script>
What am I doing wrong?
Thank you in advance for your time and expertise.
If you are using Dojo 1.7+, you probably just forgot to require the "dijit/registry" module. This where the byId function is defined. When you use desktop widgets, this is loaded indirectly by other base modules, but with dojox/mobile you must load it explicitly (because dojox/mobile loads only a very minimal set of modules by default, to minimize code footprint).
Depending on how you wrote your application, do this:
dojo.require("dijit.registry"); // legacy (pre-1.7) loader syntax
...
var rrlOppsContainer = dijit.byId("rrlOpps");
...
or this:
require(["dijit/registry", ...], function(registry, ...){ // 1.7+ AMD loader syntax
...
var rrlOppsContainer = registry.byId("rrlOpps");
...
});
Note also that your second code sample tries to use asynchronous loading (async: true) while it uses the legacy loader syntax. This won't work, to get async loading you must use the AMD syntax.

Safari Extension Questions

I'm in the process of building my first Safari extension--a very simple one--but I've run into a couple of problems. The extension boils down to a single, injected script that attempts to bypass the native feed handler and redirect to an http:// URI. My issues so far are twofold:
The "whitelist" isn't working the way I'd expect. Since all feeds are shown under the "feed://" protocol, I've tried to capture that in the whitelist as "feed://*/*" (with nothing in the blacklist), but I end up in a request loop that I can't understand. If I set blacklist values of "http://*/*" and "https://*/*", everything works as expected.
I can't figure out how to access my settings from my injected script. The script creates a beforeload event handler, but can't access my settings using the safari.extension.settings path indicated in the documentation.
I haven't found anything in Apple's documentation to indicate that settings shouldn't be available from my script. Since extensions are such a new feature, even Google returns limited relevant results and most of those are from the official documentation.
What am I missing?
UPDATE
So I'm hoping that the documentation is incomplete because it's borderline abysmal, but I've learned a bit about settings. It turns out that, from injection scripts, the SafariExtensionSettings object isn't available. Injection scripts only have access to the SafariContentExtension object (which isn't useful at all), but it's aliased in exactly the same manner (safari.extension.settings)--bad idea, IMO. As stated in the injection script documentation:
Important: When you use safari.extension from within an injected script, you are not addressing the SafariExtension class. You are addressing the SafariContentExtension class.
You have to use the messaging system to talk to a global HTML file which has access to the settings. It's kind of loopy, but I have a message being sent to a global.html file that retrieves the settings and will send a message back to my injection script as soon as I figure out how to go about doing that.
Since I'm doing all of my work before the document loads, all of the methods I've found to send message back rely on a page object that I don't have.
Like everyone else at this point, I'm still climbing the learning curve, but here's how I've handled this problem:
I have a simple extension with no chrome and one injected end script (script.js). For the purpose of loading settings I've added a simple global page (proxy.html). When script.js is injected, it sends a getSettings message to proxy.html. proxy.html responds with a setSettings message, and script.js continues initialization.
The most helpful page I've found in the docs on this topic is Messages and Proxies.
proxy.html:
<!doctype html>
<html lang="en">
<head>
<script type="text/javascript">
safari.application.addEventListener( "message", function( e ) {
if( e.name === "getSettings" ) {
e.target.page.dispatchMessage( "setSettings", {
sort_keys: safari.extension.settings.getItem( "sort_keys" )
} );
}
}, false );
</script>
</head>
<body></body>
</html>
script.js:
( function() {
var settings, init = function() {
// do extension stuff
};
// listen for an incoming setSettings message
safari.self.addEventListener( "message", function( e ) {
if( e.name === "setSettings" ) {
settings = e.message;
init();
}
}, false );
// ask proxy.html for settings
safari.self.tab.dispatchMessage( "getSettings" );
}() )
EDIT: like you said in your initial post update, the injected script doesn't have the same kind of access that a global HTML page would have. This is my working solution, imagine you want to know the value of setting "foo" in the injected script:
Injected script code:
function getMessage(msgEvent) {
if (msgEvent.name == "settingValueIs")
alert("Value for asked setting is: " + msgEvent.message);
}
safari.self.tab.dispatchMessage("getSettingValue", "foo"); // ask for value
safari.self.addEventListener("message", getMessage, false); // wait for reply
Global HTML code:
function respondToMessage(messageEvent) {
if (messageEvent.name == "getSettingValue") {
// getItem("foo");
var value = safari.extension.settings.getItem(messageEvent.message);
// return value of foo to injected script
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("settingValueIs", value);
}
}
safari.application.addEventListener("message",respondToMessage,false);
Hope this helps !
Initial post: I'm having the same 2nd problem as you, I can't access my settings (or secureSettings) from an injected script. In my case the script is loaded after page load, but even that way I can't use safari.extension.settings.
The only way it works is with a toolbar/button, the HTML behind that element can getItem and setItem as expected.
My conclusion is that, for some reason, injected scripts can't access settings (actually, they don't even seem to have access to the safari element). Bug or intended feature, that's left to figure out.
It took me several days, but I think I found a workable solution using the canLoad() messaging method. My injection script retrieves settings by calling the global HTML page like this:
settings = safari.self.tab.canLoad( event );
My global HTML file, in turn, returns those settings as:
settings = {
'setting1': safari.extension.settings.getItem( 'setting1' )
}
msgEvent.message = settings;
It's still a bit more "hacky" than I'd like. I can't seem to simply return the settings object itself, so I have to compile a new object by retrieving each setting manually. Not ideal, but it does seem to be effective.
run into the same problem, but the answer is easier than you can imagine: include the script in your global html.
<!DOCTYPE HTML>
<script type="text/javascript" src="cleanup.js"></script>
<script>
…
</script>
then you can access the settings as described in documentation safari.extension.settings.myKey
you can also upvote #Travis, because I got the idea from his post
//EDIT:
actually I don't really know whats wrong. Calling the settings as the first command works, but not at a later time. Additionally it seems to corrupting my complete script after the 2. injection. Need verification if it's only in my (difficult?) script.
//EDIT2:
now I got it to work to get back the settings object via dispatchMessage()
in your injected.js
function gotSettings(msgEvent) {
if (msgEvent.name === "SETTINGS") {
setts = msgEvent.message;
alert(setts.mySetting1);
// run the programm
}
}
safari.self.addEventListener("message", gotSettings, false);
safari.self.tab.dispatchMessage("getSettings");
and in global.html
switch (event.name) {
case "getSettings":
// send the settings data
event.target.page.dispatchMessage("SETTINGS", safari.extension.settings);
relying on this apple documentation