Chandra
view release on metacpan or search on metacpan
examples/contextmenu_example.pl view on Meta::CPAN
log_action('Increase Font');
}, shortcut => 'Ctrl+=' },
{ label => 'Decrease Font', action => sub {
$app->eval("var e=document.getElementById('editor');var s=parseFloat(getComputedStyle(e).fontSize);if(s>8)e.style.fontSize=(s-2)+'px';");
log_action('Decrease Font');
}, shortcut => 'Ctrl+-' },
]);
# ---- Dynamic context menu on list items ----
$app->context_menu('.list-item', sub {
my ($target) = @_;
my $id = $target->{id} || 'unknown';
my $name = $id;
$name =~ s/^file-//;
return [
{ label => "Open $name", icon => "\x{1f4c4}", action => sub {
$app->eval("document.getElementById('editor').textContent='# Contents of $name\\n# (loaded from sidebar)\\nprint \"Editing $name\\\\n\";\\n';");
$app->eval("document.querySelectorAll('.list-item').forEach(function(el){el.style.background='';});document.getElementById('$id').style.background='#b8d4f0';");
log_action("Opened $name");
} },
{ label => "Rename $name", icon => "\x{270f}", action => sub {
$app->eval("var el=document.getElementById('$id');el.textContent='renamed-'+el.textContent;");
log_action("Renamed $name");
} },
{ label => "Duplicate $name", icon => "\x{2398}", action => sub {
$app->eval("var el=document.getElementById('$id');var cl=el.cloneNode(true);cl.id='';cl.textContent=el.textContent+' (copy)';el.parentNode.insertBefore(cl,el.nextSibling);");
log_action("Duplicated $name");
} },
{ separator => 1 },
{ label => "Delete $name", icon => "\x{1f5d1}", action => sub {
$app->eval("var el=document.getElementById('$id');if(el)el.remove();");
log_action("Deleted $name");
} },
];
});
sub log_action {
my ($msg) = @_;
$app->eval(
"document.getElementById('log').innerHTML += "
. "'<div class=\"log-entry\">" . $msg . "</div>';"
. "document.getElementById('log').scrollTop = "
. "document.getElementById('log').scrollHeight;"
);
}
$app->set_content(<<'HTML');
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
margin: 0; display: flex; flex-direction: column; height: 100vh;
background: #f5f5f5; color: #333; }
.header { padding: 12px 16px; background: #2c3e50; color: white;
font-size: 14px; font-weight: 600; }
.main { display: flex; flex: 1; overflow: hidden; }
.sidebar { width: 200px; background: #ecf0f1; border-right: 1px solid #ddd;
padding: 8px 0; overflow-y: auto; }
.list-item { padding: 8px 16px; cursor: pointer; font-size: 13px; }
.list-item:hover { background: #dfe6e9; }
#editor { flex: 1; padding: 16px; font-family: monospace; font-size: 13px;
white-space: pre-wrap; background: #fff; overflow-y: auto;
line-height: 1.6; min-height: 200px; }
#log { height: 120px; overflow-y: auto; background: #2d2d2d; color: #0f0;
font-family: monospace; font-size: 12px; padding: 8px; border-top: 2px solid #444; }
.log-entry { padding: 2px 0; }
.hint { color: #888; font-size: 12px; padding: 8px 16px; background: #fafafa;
border-top: 1px solid #eee; }
</style>
</head>
<body>
<div class="header">Context Menu Example</div>
<div class="main">
<div class="sidebar">
<div class="list-item" id="file-readme">README.md</div>
<div class="list-item" id="file-main">main.pl</div>
<div class="list-item" id="file-config">config.yml</div>
<div class="list-item" id="file-test">test.t</div>
<div class="list-item" id="file-lib">lib/App.pm</div>
</div>
<div id="editor">use strict;
use warnings;
sub hello {
my ($name) = @_;
print "Hello, $name!\n";
}
hello("World");
</div>
</div>
<div class="hint">Right-click on the editor or file list items to see context menus</div>
<div id="log"></div>
</body>
</html>
HTML
$app->run;
( run in 1.028 second using v1.01-cache-2.11-cpan-140bd7fdf52 )