###################################
# CUSTOMIZING THE ENTRIES (V4.0) #
# kunzite1 and xtomxfallsx, #
# component_help/949747 #
# overrides: #
# Entry::print_metadata() #
# CommentInfo::print() #
# Entry::print_linkbar() #
# print_entry() #
###################################
# activate tags
set tags_aware = true;
# add colons to text because i didn't like them being hard-coded inside print_metadata()
set text_meta_groups = "Current Groups:";
set text_meta_location = "Current Location:";
set text_meta_mood = "Current Mood:";
set text_meta_music = "Current Music:";
function Entry::print_metadata() {
var string tags_header = "Current Tags"; # text for tags header, "Current Tags"
var string tags_joiner = ":"; # text for tags joiner, ":"
var string tags_sep = ", "; # text for tags separator, ", "
var bool show_edit_tags_link = false; # set to true if you want edit tags link as tags header
var string currents_open = ""; # html for opening of currents container
var string currents_close = ""; # html for closing of currents container
var bool loc_after_mood = false; # set to true to print location after mood
var bool vanilla_loc = false; # set to true to delinkify location
var string meta_label_open = """<strong>"""; # html for opening of metadata label
var string meta_label_close = """</strong> """; # html for closing of metadata label
var string meta_val_open = ""; # html for opening of metadata value
var string meta_val_close = """<br />"""; # html for closing of metadata value
var Link edit_tags = $this->get_link("edit_tags"); # helper var to see if remote user can edit tags
if ((size $.metadata > 0) or ((size $.tags > 0) and ($*tags_aware))){
if($.metadata{"mood"} == "" and $loc_after_mood) {
# if we're printing loc after mood but we have no mood, set loc_after_mood to false
$loc_after_mood = false;
}
var string currents = ""; # make var for printing
$currents = $currents_open; # add opening of currents container
foreach var string k ($.metadata){ # step thru metadata
var string text = $k; # set text to key
var string val = $.metadata{$k}; # get val
if ($k == "mood"){ # if mood, set text to mood property
$text = $*text_meta_mood;
if(defined $.mood_icon) {
var Image i = $.mood_icon;
$val = """<img src="$i.url" width="$i.width" height="$i.height" alt="$val" title="$val" /> $val""";
}
}
elseif ($k == "music") { # if music, set text to music property
$text = $*text_meta_music;
} elseif ($k == "location") { # if location, set text to loc variable
$text = $*text_meta_location;
if($vanilla_loc) { # if vanilla loc, striphtml() it
$val = striphtml($val);
}
}
if(not ($k == "location" and $loc_after_mood)) {
# if we're doing loc right now and printing loc after mood, skip it
# if we're doing loc right now and we're not printing loc after mood, print it now
# if we're not doing loc right now, print this piece of meta
# add the meta
$currents = $currents + """$meta_label_open$text$meta_label_close$meta_val_open$val$meta_val_close""";
}
if($k == "mood" and $loc_after_mood) {
# if we just now did the mood and we're printing loc after mood, print the loc
$k = "location"; # set meta key to "location"
$text = $*text_meta_location; # set text to loc variable
$val = $.metadata{$k}; # get val
# if we have a loc, do stuff
if($val != "") {
# if vanilla loc, striphtml() it
if($vanilla_loc) {
$val = striphtml($val);
}
# add the meta
$currents = $currents + """$meta_label_open$text$meta_label_close$meta_val_open$val$meta_val_close""";
}
}
}
if ((size $.tags > 0) and $*tags_aware) {
var string k = "tags"; # set key to "tags"
var int tcount = 0; # set counter for tags
if($edit_tags.url != "" and $show_edit_tags_link) { # if remote user can edit tags, let's give them a link
$tags_header = """<a href="$edit_tags.url">$tags_header</a>""";
}
# add text, open val container
$currents = $currents + """$meta_label_open$tags_header$tags_joiner$meta_label_close$meta_val_open""";
# build tag list
foreach var Tag t ($.tags) {
$currents = $currents + """<a rel="tag" href="$t.url">$t.name</a>""";
$tcount++;
# if we haven't hit the last tag, add a separator
if ($tcount != size $.tags) { $currents = $currents + $tags_sep; }
}
# close val container
$currents = $currents + $meta_val_close;
}
# close currents container
$currents = $currents + $currents_close;
# print currents
println "$currents";
}
}
function CommentInfo::print_readlink() {
var string img_url = "";
var int img_width = 0;
var int img_height = 0;
var bool img_count = false;
if($.show_readlink) {
var Page p = get_page();
var string url = $.read_url;
var string text = get_plural_phrase($.count, "text_read_comments" + ($p.view == "friends" ? "_friends" : ""));
if($.screened) {
$text = $text + " " + $*text_month_screened_comments;
}
if($url != "") {
"""<a href="$url">""";
}
if($img_url != "") {
if($img_count) {
print $.count;
}
"""<img src="$img_url" width="$img_width" height="$img_height" alt="$text" title="$text" border="0" />""";
} else {
print $text;
}
if($url != "") {
"""</a>""";
}
}
}
function CommentInfo::print_postlink() {
var string img_url = "";
var int img_width = 0;
var int img_height = 0;
if($.show_postlink) {
var Page p = get_page();
var string url = $.post_url;
var string text = get_plural_phrase(0, "text_post_comment" + ($p.view == "friends" ? "_friends" : ""));
if($.maxcomments) {
$url = "";
$text = $*text_max_comments;
}
if($url != "") {
"""<a href="$url">""";
}
if($img_url != "") {
"""<img src="$img_url" width="$img_width" height="$img_height" alt="$text" title="$text" border="0" />""";
} else {
print $text;
}
if($url != "") {
"""</a>""";
}
}
}
function CommentInfo::print() {
var string text_comment_divider = $*comment_divider;
if($.show_readlink) {
$this->print_readlink();
if($.show_postlink) {
print " $text_comment_divider ";
}
}
if($.show_postlink) {
$this->print_postlink();
}
}
function Entry::print_linkbar() {
var string linkbar_seperator = " "; # seperator for links in linkbar (edit/mem/tags)
var string{} linkbar_captions = { # linkbar captions
"edit_entry" => "$*text_edit_entry",
"edit_tags" => "$*text_edit_tags",
"flag" => "$*text_flag",
"mem_add" => "$*text_mem_add",
"nav_prev" => "$*text_entry_prev",
"nav_next" => "$*text_entry_next",
"tell_friend" => "$*text_tell_friend",
"watch_comments" => "$*text_watch_comments",
"unwatch_comments" => "$*text_unwatch_comments",
};
var string{} linkbar_images = { # linkbar images;
"edit_entry" => "$*edit_img",
"edit_tags" => "$*tags_img",
"flag" => "$*flag_img",
"mem_add" => "$*mem_img",
"nav_prev" => "$*backarrow2",
"nav_next" => "$*forwardarrow2",
"tell_friend" => "$*tellfriend_img",
"watch_comments" => "$*track_img",
"unwatch_comments" => "$*untrack_img",
};
# get Page handle
var Page p = get_page();
# get Entry handle
var Entry e = $this;
# initialize array/hashes
var string[] link_keyseq = [""];
var string{} link_url = {"" => ""};
var string{} link_caption = {"" => ""};
var string{} link_image = {"" => ""};
$link_caption = $linkbar_captions;
$link_image = $linkbar_images;
var string linkbar = ""; # var for printing
var bool show_interentry = ($p.view == "entry" or $p.view == "reply"); # if entry/reply view, show interentry
var int keyseq_index = 0; # set index point for new link_keyseq array
if($show_interentry) {
# if show interentry, put previous entry link first
$link_keyseq[$keyseq_index++] = "nav_prev";
# get previous entry link information
var Link prev = $e->get_link("nav_prev");
$link_url{"nav_prev"} = $prev.url;
# get next entry link information
var Link next = $e->get_link("nav_next");
$link_url{"nav_next"} = $next.url;
}
# gather current linkbar
foreach var string link_key ($e.link_keyseq) {
var Link link = $e->get_link($link_key);
$link_url{$link_key} = $link.url;
$link_caption{$link_key} = $link_caption{$link_key} != "" ? $link_caption{$link_key} : $link.caption;
$link_image{$link_key} = $link_image{$link_key} != "" ? $link_image{$link_key} : $link.icon.url;
$link_keyseq[$keyseq_index++] = $link_key; # add this to new link_keyseq array
}
if($show_interentry) {
# if show interentry, put next entry link last
$link_keyseq[$keyseq_index++] = "nav_next";
}
#################################################################################################################
# by now, the above hashes should look something like: #
# #
# If interentry: #
# Previous Entry: #
# $link_url{"nav_prev"} = http://www.livejournal.com/go.bml?journal=exampleusername&itemid=256&dir=prev #
# $link_caption{"nav_prev"} = Previous Entry #
# $link_image{"nav_prev"} = http://stat.livejournal.com/img/btn_prev.gif #
# #
# Edit Entry: #
# $link_url{"edit_entry"} = http://www.livejourna.com/editjournal.bml?journal=exampleusername&itemid=256 #
# $link_caption{"edit_entry"} = Edit Entry #
# $link_image{"edit_entry"} = http://stat.livejournal.com/img/btn_edit.gif #
# #
# Edit Tags: #
# $link_url{"edit_tags"} = http://www.livejournal.com/edittags.bml?journal=exampleusername&itemid=256 #
# $link_caption{"edit_tags"} = Edit Tags #
# $link_image{"edit_tags"} = http://stat.livejournal.com/img/btn_edittags.gif #
# #
# Add to Memories: #
# $link_url{"mem_add"} = http://www.livejournal.com/tools/memadd.bml?journal=exampleusername&itemid=256 #
# $link_caption{"mem_add"} = Add to Memories #
# $link_image{"mem_add"} = http://stat.livejournal.com/img/btn_memories.gif #
# #
# If interentry: #
# Next Entry: #
# $link_url{"nav_next"} = http://www.livejournal.com/go.bml?journal=exampleusername&itemid=256&dir=next #
# $link_caption{"nav_next"} = Next Entry #
# $link_image{"nav_next"} = http://stat.livejournal.com/img/btn_next.gif #
#################################################################################################################
# loop thru linkbar and add links to print var
foreach var string link_key ($link_keyseq) {
# if we can do performed action, url will be present
if($link_url{$link_key} != "") {
$linkbar = $linkbar + """<a href="$link_url{$link_key}">""";
# if image url available, use it
if($link_image{$link_key} != "") {
$linkbar = $linkbar + """<img src="$link_image{$link_key}" alt="$link_caption{$link_key}" title="$link_caption{$link_key}" border="0" />""";
} else {
# else, just use text
$linkbar = $linkbar + "$link_caption{$link_key}";
}
# add a seperator
$linkbar = $linkbar + "</a>$linkbar_seperator";
}
}
# hack off last seperator
$linkbar = $linkbar->substr(0, $linkbar->length() - $linkbar_seperator->length());
print $linkbar;
}
### Override the printing of entries. This affects the Recent/Friends/Day/Entry pages.</span>
function print_entry(Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text) {
# USER VARS
var string meta_pos = "bottom"; # metadata at top or bottom?
var string icon_side = "left"; # userpics on the left or right side?
var string icon_pos = "outside"; # userpics inside or outside entries?
var bool show_border = false; # if inside, show a border around userpics?
var bool meta_wrap = false; # if inside force metadata to print below
# userpic rather than to the left or right
# of it in cases of very short entries
var bool show_recent_userpic = $*show_entry_userpic; # show userpic on recent page?
var bool show_friends_userpic = true; # show userpic on friends page?
var bool show_day_userpic = false; # show userpic on day page?
var bool show_entry_userpic = $*show_entrypage_userpic; # show userpic on entry page?
var bool show_reply_userpic = $*show_entrypage_userpic; # show userpic on reply page?
var bool scroll_recent_entry = true; # scrolling entry on recent page?
var bool scroll_friends_entry = true; # scrolling entry on friends page?
var bool scroll_day_entry = true; # scrolling entry on day page?
var bool scroll_entry_entry = false; # scrolling entry on entry page?
var bool scroll_reply_entry = true; # scrolling entry on reply page?
var string{} sec_urls = { # security images
"groups" => "$*IMGDIR/icon_groups.gif",
"public" => "http://pics.livejournal.com/kunzite1/pic/000f5p4c",
"protected" => "$*IMGDIR/icon_protected.gif",
"private" => "$*IMGDIR/icon_private.gif",
};
var string{} sec_alts = { # security captions
"groups" => "$*text_icon_alt_groups",
"public" => "[public post]",
"protected" => "$*text_icon_alt_protected",
"private" => "$*text_icon_alt_private",
};
#/USER VARS
# build id
var string id = ($p.view == "friends" ? $e.journal.username : "item") + $e.itemid;
$id = """<a name="$id" id="$id"></a>""";
#/build id
# build entry header and security
var string entry_header = "";
var string security = $e.security != "" ? $e.security : "public";
# normal entry header
if($sec_urls{$security} != "") {
$entry_header = $entry_header + """<img src="$sec_urls{$security}" alt="$sec_alts{$security}" title="$sec_alts{$security}" /> """;
}
$entry_header = $entry_header + $e.time->time_format();
$entry_header = $entry_header + " ";
$entry_header = $entry_header + ($e.new_day ? "<b>" : "");
$entry_header = $entry_header + $e.time->date_format("long");
$entry_header = $entry_header + ($e.new_day ? "</b>" : "");
#/build entry header and security
# use $id to print anchor string for entry
# use $entry_header to print_entry_header($entry_header);
# use $e->print_metadata() to print metadata (mood/music/tags)
# use $e.comments->print() to print comments (comment links)
# use $e->print_linkbar() to print linkbar (edit entry/mem add/edit tags/tell friend/etc)
# use $show_poster to see if we're going to show poster/journal info
# use $show_userpic to see if we're going to show the userpic
# build userpic and posterinfo
# don't edit these
var bool show_poster = ($p.view == "friends" or $p.journal.journal_type == "C"); # figure out if we're going to show poster info
var bool show_userpic = false; # figure out if we're going to show userpic
var bool scroll_entry = false; # figure out if we're going to make a scrolling entry
var bool have_meta = false; # figure out if we have metadata to print
var string padding_pos = ""; # set padding based upon icon pos
var string iconborder = ""; # var for icon border code
var string icon_data = ""; # var for icon data
$padding_pos = (($icon_side == "left") or ($icon_side == "right")) ? (($icon_side == "left") ? "right" : "left") : "";
$icon_data = "";
$show_userpic = (
defined $e.userpic and
(
(($p.view == "recent") and $show_recent_userpic ) or
(($p.view == "friends") and $show_friends_userpic) or
(($p.view == "day") and $show_day_userpic ) or
(($p.view == "entry") and $show_entry_userpic ) or
(($p.view == "reply") and $show_reply_userpic )
)
);
$scroll_entry = (
(($p.view == "recent") and $scroll_recent_entry ) or
(($p.view == "friends") and $scroll_friends_entry) or
(($p.view == "day") and $scroll_day_entry ) or
(($p.view == "entry") and $scroll_entry_entry ) or
(($p.view == "reply") and $scroll_reply_entry )
);
$have_meta = (
( size($e.metadata) > 0) or
((size($e.tags) > 0) and $*tags_aware)
);
var string scrolling = $scroll_entry ? " class=\"fixed\"" : "";
# Print the anchor to be used in the page summary.
print $id;
# Print the header for the entry.
print_entry_header($entry_header);
"""
<table cellspacing="0" cellpadding="0" border="0" width="100%"$scrolling>
<tr>
<td width="1" class="dkLine"><img src="$*PALIMGROOT/component/clear.gif" width="1" height="1" alt="" border="0" /></td>
<td class="entryHolderBg" width="100%">
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>""";
# Check to see if we need to display a usericon and/or journal names, and if so, then print them
# Cases - 1. We are viewing a friends page, so we need to display icons if they exist and journal/poster names
# 2. We are viewing a recent/day/entry page, so we display only the icon if it exists and
# the user has set recent userpics on.
if ($show_poster or $show_userpic) {
# If the icon position is set to inside do this
if ($icon_pos == "inside") {
# If we have chosen to show the border, this will set the code. The border will be the same color as entry text.
# If you want a different color, change the maroon bit below to whichever color you'd like.
if ($show_border) {
$iconborder = " border: thin solid $*entry_fgcolor;";
}
# Build the div that will hold the icon, poster name, and community name.
# It is set to center the names below the image. If you'd like to change that,
# change the maroon text blow to either left or right.
$icon_data = $icon_data + """
<div style="text-align: center; padding: 2px; float: $icon_side; margin-$padding_pos: 4px; margin-bottom: 4px;$iconborder">\n""";
# Display the icon if it exists
if ($show_userpic) {
if ($show_poster and $show_userpic) {
$icon_data = $icon_data + """<div style="padding: 3px; background-color: $bgcolor;"><a href="$*SITEROOT/allpics.bml?user=$e.poster.username"><img border="0" src="$e.userpic.url" width="$e.userpic.width" height="$e.userpic.height" alt="$e.poster.name" title="$e.poster.name" style="border-color: $fgcolor;" /></a></div>""";
} else {
$icon_data = $icon_data + """<div style="padding: 3px;"><img border="1" src="$e.userpic.url" width="$e.userpic.width" height="$e.userpic.height" alt="" /></div>""";
}
}
# Display the journal and possibly poster name if we are viewing the friends page or any page on a community
# This code will print the journal the entry was made on, and if the poster is different, will print the poster under it.
if ($show_poster) {
$icon_data = $icon_data + """<div class="ljuser">$e.journal""";
if ($e.journal.username!=$e.poster.username) {
$icon_data = $icon_data + "<br />$e.poster";
}
$icon_data = $icon_data + """</div>""";
}
$icon_data = $icon_data + """</div>""";
# End icon inside section
} else {
# Otherwise, if icon position is set to outside, do this
# Start the table that will hold the icon and/or names
$icon_data = $icon_data + """
<td valign="top" style="padding-$padding_pos: 8px;">
<table cellspacing="0" cellpadding="0" border="0" align="center">
<tr>
<td>
<img src="$*PALIMGROOT/component/clear.gif" width="1" height="1" alt="" border="0" />
</td>
</tr>""";
# Display the icon if it exists
if ($show_userpic) {
$icon_data = $icon_data + """
<tr>
<td>
<img src="$*PALIMGROOT/component/clear.gif" width="1" height="2" alt="" border="0" />
</td>""";
if ($show_poster and $show_userpic) {
$icon_data = $icon_data + """
<td>
<div style="padding-top: 3px; padding-left: 3px; padding-right: 3px; padding-bottom: 3px; background-color: $bgcolor;" align="center"><a href="$*SITEROOT/allpics.bml?user=$e.poster.username"><img border="0" src="$e.userpic.url" width="$e.userpic.width" height="$e.userpic.height" alt="$e.poster.name" title="$e.poster.name" style="border-color: $fgcolor;" /></a></div>
</td>""";
} else {
$icon_data = $icon_data + """
<td align="center" class="userpic"><img border="1" src="$e.userpic.url" width="$e.userpic.width" height="$e.userpic.height" alt="" /></td>""";
}
$icon_data = $icon_data + """
</tr>""";
}
# Display the journal and possibly poster name if we are viewing the friends page or any page on a community
# This code will print the journal the entry was made on, and if the poster is different, will print the poster under it.
# I made the names centered under the image, but if you want to keep them left aligned as in the original, then
# remove the blue segments
if ($show_poster) {
$icon_data = $icon_data + """
<tr>
<td>
<img src="$*PALIMGROOT/component/clear.gif" width="1" height="2" alt="" border="0" />
</td>
<td align="center" class="ljuser">$e.journal""";
if ($e.journal.username!=$e.poster.username) {
$icon_data = $icon_data + """
<div align="center" class="ljuser">$e.poster</div>""";
}
$icon_data = $icon_data + """
</td>
</tr>""";
}
$icon_data = $icon_data + """
</table>
</td>""";
}
# End icon outside section
}
# End icon section
# if icon position is outside left, stick it here
if ($icon_pos == "outside" and $icon_side == "left") {
print $icon_data;
}
# Start the main entry text area
"""<td width="100%" valign="top">""";
print_content_top();
# If the subject is not empty, then print it followed by the line to seperate it from the entry text
# You can modify the lines in maroon if you want to adjust the way your subject prints, but the other lines must remain as is.
if ($e.subject != "") { """
<div class="entryHeader">$e.subject</div>
<div class="entryDash"><img src="$*PALIMGROOT/component/clear.gif" width="1" height="1" alt="" border="0" /></div>
</td>
<td width="1" class="medLine"><img src="$*PALIMGROOT/component/clear.gif" width="1" height="1" alt="" border="0" /></td>
</tr>
<tr>
<td width="1" class="medLine"><img src="$*PALIMGROOT/component/clear.gif" width="1" height="1" alt="" border="0" /></td>
<td class="entry">
"""; }
# Place a <div> around entry text and metadata, compliant with scrolling entries tutorial.
"""<div class="scrollentry">""";
# If icon position is inside left or right, stick it in here
if ($icon_pos == "inside") {
print $icon_data;
}
# If metadata is at top, stick it here
# Add a blank line
if($have_meta) {
if($meta_pos == "top") {
$e->print_metadata();
print "<br /><br />";
}
}
# Print the entry text.
$e->print_text();
# If metadata is at bottom, stick it here
if ($have_meta) {
if($meta_pos == "bottom") {
# if we have chosen to force the metadata to wrap below
# the userpic, create a div to clear the image
if ($meta_wrap) {
print """<div style="clear: both;"><br /></div>""";
} else {
print "<br /><br />";
}
# print metadata
$e->print_metadata();
}
}
# Close <div> around entry text and metadata.
"""</div>""";
# Close off the entry text area
print_content_bottom();
# This is where the fun stuff is!
# Now we begin the area underneath the entry that holds the comments, link, and entry related buttons.
# First we print the comment links if the entry allows comments
"""
<table width="100%">
<tr>
<td width="50%" align="left" valign="center">
<div class="entryComments">"""; $e.comments->print(); """</div>
</td>
""";
# Then print a permanent link to the entry.
# I have this because I have my journal set to display comment links with "?nc=XX" tacked onto the end,
# and when I'm copying and pasting links, it's annoying to have there. Also, if you want a link to
# an entry that has no comments yet, the only link that's shown by default is the reply to link, and that
# that includes "?mode=reply" which is also annoying to have to remove.
# Essentially this is here for convenience. If you don't want it, remove the blue segment.
"""
<td align="center" valign="center">
<div class="entryComments"><span style="white-space:nowrap;"><b>( <a href="$e.permalink_url" class="commentLinks">$*text_permalink</a> )<b></span></div>
</td>
""";
# Then the entry related buttons
"""
<td width="50%" align="right" valign="center">
<div class="entryComments">"""; $e->print_linkbar(); """</div>
</td>
</tr>
</table>
""";
# if icon position is outside right, stick it here
if ($icon_pos == "outside" and $icon_side == "right") {
print $icon_data;
"""</td>""";
}
# End the entry component and put a spacer after it so that entry components are seperated.
"""
</tr>
</table>""";
print_system_box_bottom();
""" <div><img src="$*PALIMGROOT/component/clear.gif" width="3" height="3" alt="" border="0"></div> """;
} # end of Function print_entry
########################################
# SCROLLING ENTRIES #
# for use with CUSTOMIZING THE ENTRIES #
# found at component-help/949747 #
# overrides: #
# Page::print_custom_head #
# if you already have this func #
# add it to your existing func #
########################################
function Page::print_custom_head() {
"""
<style type="text/css">
/* edit the width and height values to suit your needs */
/* you can use pixels instead of percentages */
.scrollentry {
width: 80%;
height: 100%;
overflow: auto;
padding-bottom: 17px;
}
</style>
""";
}
customizing the entries v4.0
-
Chemo-Sabe: Help Save Mike!
I posted a while back about my adventures in cancer treatment. Well, we've hit a snag. It's gone on longer than we had anticipated and we're moving…
-
A reach out for help
Hello. I'm
kunzite1. I helped create this community back in the early days of LiveJournal. I have been absent from the community for…
-
maintainer help?
hello. it's been forever and a day since i've been here. sorry. :( i know that the tutorial entries are hosed. sorry. :( i'm looking for someone…
-
Chemo-Sabe: Help Save Mike!
I posted a while back about my adventures in cancer treatment. Well, we've hit a snag. It's gone on longer than we had anticipated and we're moving…
-
A reach out for help
Hello. I'm
kunzite1. I helped create this community back in the early days of LiveJournal. I have been absent from the community for…
-
maintainer help?
hello. it's been forever and a day since i've been here. sorry. :( i know that the tutorial entries are hosed. sorry. :( i'm looking for someone…
← Ctrl ← Alt
Ctrl → Alt →
← Ctrl ← Alt
Ctrl → Alt →