November 27, 2024

Luka Doncic’s triple-double powers Mavericks past Raptors 114-110

Luka #Luka

DALLAS

The Associated Press

Published May 15, 2021 Updated May 15, 2021

For Subscribers

Getting audio file …

Audio for this article is not available at this time.

This translation has been automatically generated and has not been verified for accuracy. Full Disclaimer

Dallas Mavericks guard Luka Doncic dunks during the fourth quarter against the Toronto Raptors at American Airlines Center. The Mavs beat the Raptors 114-110 on May 14, 2021.

Kevin Jairaj/USA TODAY Sports via Reuters

Luka Doncic had his 11th triple-double of the season with 20 points, 10 rebounds and 11 assists and the Dallas Mavericks guaranteed themselves a top-six finish in the Western Conference, to avoid the NBA’s play-in next week, with a 114-110 victory over Toronto on Friday night.

Kristaps Porzingis, who finished with 21 points and 10 rebounds, made a 3-pointer on the game’s first shot and the Mavericks never trailed in their regular-season home finale, though the undermanned Raptors cut it close late. Toronto used only seven players, going without its top seven scorers – mostly because of injuries, but also with the season winding down and the Raptors out of contention for even a play-in spot in the East.

Toronto, which trailed by 19 points early in the second half, was within 105-102 on Malachi Flynn’s 3-pointer with three minutes left, which followed a Mavericks turnover after his layup. But Dorian Finney-Smith responded with a 3-pointer for Dallas and Doncic then drove for a one-handed slam. Doncic had earlier rebounded his own missed short jumper and followed that with a nifty layup.

Story continues below advertisement

Raptors rookie Jalen Harris, a Dallas native making his second career start in as many nights, had 31 points to lead Toronto. Flynn had 26 points.

The Southwest Division-winning Mavericks (42-29) are in fifth place in the West, with a one-game lead over Portland (41-30) for the No. 5 seed with one regular-season game remaining for both teams. The Trail Blazers have the tiebreaker if they finish with the same record, since they won two of three against Dallas this season.

Teams finishing seventh through 10th in each conference are forced into play-in games next week to determine who advances. The top six teams get an extended break after a condensed regular-season schedule, though with 10 fewer games than usual, because of the pandemic.

BAYLOR CONNECTION

Toronto rookie forward Freddie Gillespie from Baylor got his first career NBA start, and it came on a night when the Baylor coach Scott Drew and the national champion Bears were in attendance to be recognized by the Mavericks. Dallas County officials declared May the month of the Bears in the county.

TIP-INS

Raptors: Stanley Jonson had a double-double with 15 points and 10 rebounds. … Toronto extended a franchise record with its 37th different starting lineup this season. It was the ninth game in a row they used a different starting five.

Mavericks: It was the 36th career triple-double for Doncic, who is 11th on the NBA career list. He is still seven behind Fat Lever for the top 10, but now three ahead of Bob Cousy. … Jalen Brunson finished with 19 points and Finney-Smith had 17. … Dallas had lost 12 of its previous 16 games against the Raptors, including 116-93 in Tampa on Jan. 18.

UP NEXT

Raptors: Regular-season “home” finale against Indiana on Sunday in Tampa.

Story continues below advertisement

Mavericks: Regular-season finale at Minnesota.

“, “

Save time by making it easy to scan all the latest stories on topics you follow in one place.

“, “”, “

Learn More

” ].join(“”); var content2 = [ “”, “”, “

Adding topics. Click on the + symbol to save the topic to your Following page.

“, “”, “

(Step 1 of 3)

“, “

“, “Previous”, “Next”, “

” ].join(“”); var content3 = [ “”, “”, “

Clicking on the topic’s name will bring you to a page where you can view all the articles that pertain to that topic.

“, “”, “

(Step 2 of 3)

“, “

“, “Previous”, “Next”, “

” ].join(“”); var content4 = [ “”, “”, “Access your following topics by clicking on your display name.“, “

Access your following topics by clicking on your display name. The number in your display name indicates the number of new articles you haven’t read from your following topics.

“, “”, “

(Step 3 of 3)

“, “

“, “Previous”, “Got it”, “

” ].join(“”); var contentMarkup = [content1, content2, content3, content4]; function createTourtip() { var relatedTopics = document.querySelector(“#main-content-area .pb-f-topics-article-related .c-topic-group__body ul”); var topicPageTitle = document.querySelector(“.o-primary-header–section .c-topic”); // If the following topics buttons are present on the page, set up the tourtips if (relatedTopics || topicPageTitle) { var modifier = relatedTopics ? ‘darwin-arc6134–article’ : ‘darwin-arc6134–topic-page’ var dataAnalyticsClick = JSON.stringify({ testId: “arc6134”, type: “button”, feature: “topic tour tip”, label: “show tooltip” }); var el = relatedTopics ? document.createElement(“li”) : document.createElement(“div”); el.classList.add(“darwin-arc6134”); el.classList.add(modifier); el.innerHTML = “

“+contentMarkup[0] + “

“; relatedTopics ? relatedTopics.appendChild(el) : topicPageTitle.appendChild(el); // Remove follow topics onboarding messages and activation tooltips setTimeout(function() { var onboardingMessages = document.querySelectorAll(“.c-topic-group__body .c-onboarding-message”); var tooltips = document.querySelectorAll(“.c-topic-group__body .c-tooltip”); console.log(“[ARC-6134]: onboardingMessages: “, onboardingMessages); Array.from(onboardingMessages).forEach(function(el) { el.parentNode.removeChild(el); }); Array.from(tooltips).forEach(function(el) { el.parentNode.removeChild(el); }); }, 3000); } } function analyticsPush(type, panel, action) { if (type === “simple”) { analyticsLayer.push({ “event”: “simpleEvent”, “simpleEvent”: { “testId”: “arc6134”, “action”: “view tour slide”, “label”: “slide “+panel } }); } if (type === “click”) { analyticsLayer.push({ “event”:”clickEvent”, “clickEvent”: { “testId”: “arc6134”, “feature”: “topic tour tip”, “type”: “button”, “label”: action, } }); } } function tourtipActions() { // Open tourtips var container = document.querySelector(“.darwin-arc6134”); var activateIcon = document.querySelector(“.js-tourtip-activate”); var tourtipContainer = document.querySelector(“.darwin-arc6134__tourtip”); activateIcon.addEventListener(“click”, function() { if (!container.classList.contains(“darwin-arc6134–open”)) { container.classList.add(“darwin-arc6134–open”); tourtipContainer.removeAttribute(“hidden”); keepInViewport(); localStorage.setItem(“tgam.tourtip_icon_clicked”, true); analyticsPush(“click”, 1, “show tooltip”); analyticsPush(“simple”, 1, “”); } }); // Advance tourtip panels tourtipContainer.addEventListener(‘click’, function(e) { var tourtipPanel = tourtipContainer.getAttribute(“data-panel”); var activateIcon = document.querySelector(“.js-tourtip-activate”); var el = e.target || e.srcElement; var action = el.getAttribute(“data-action”); if (action === “next”) { tourtipPanel++; analyticsPush(“simple”, tourtipPanel, action); } else if (action === “prev”) { tourtipPanel–; analyticsPush(“simple”, tourtipPanel, action); } else { tourtipPanel = 1; tourtipContainer.setAttribute(“hidden”, true); container.classList.remove(“darwin-arc6134–open”); tourtipContainer.classList.remove(“darwin-arc6134__tourtip–leftOut”); tourtipContainer.classList.remove(“darwin-arc6134__tourtip–rightOut”); activateIcon.classList.remove(“darwin-arc6134__tourtip–leftOut”); activateIcon.classList.remove(“darwin-arc6134__tourtip–rightOut”); tourtipContainer.classList.remove(“js-tourtip–centred”); tourtipContainer.style.removeProperty(“left”); } analyticsPush(“click”, tourtipPanel, action); tourtipPanel === 4 ? tourtipContainer.classList.add(“darwin-arc6134__tourtip–last-panel”) : tourtipContainer.classList.remove(“darwin-arc6134__tourtip–last-panel”); tourtipContainer.innerHTML = contentMarkup[tourtipPanel-1]; tourtipContainer.dataset.panel = tourtipPanel; }); } function init() { console.log(“[ARC-6134] init”); var testIsEnabled = /token=arc6134/.test(window.location.search); console.log(“ARC-6134 testIsEnabled: “, testIsEnabled); var testGroup = userTestGroup(); if (testGroup === “variant” || testIsEnabled) { setUnitState(“arc6134”, “variant”); console.log(“[ARC-6134] test group: variant”); createTourtip(); tourtipActions(); intersectTourtip(); } if (testGroup === “control”) { console.log(“[ARC-6134] test group: control”); setUnitState(“arc6134”, “control”); } } init(); }]); } window.tgam.darwin.tests.after.push(dwExecute_UXTestARC6134); })(); ]]> ” ].join(“”); } return template; } /** * Generate a template for the label * @param {String} label – the label text * @returns {String} */ function displayLabel(label) { var template = “”; if (label === “opinion”) { template = [ “

“, ” “, label, “”, “

“, ].join(“”); } return template; } /** * Display “Follow”, “Following” buttons * @param {Object} tData * @returns {String} */ function displayFollowingButton(tData) { var topicName = tData.topicName; var topicSlug = tData.topicSlug; var topicType = tData.topicType; var topicImg = tData.topicImg; var isAuthor = topicType === “author”; var authorImg = isAuthor && topicImg ? “" + topicName + "” : “”; var template = isAuthor ? “/authors/” : “/topics/”; var href = window.tgam.env.baseRootAbsoluteUrl + template + topicSlug; var linkClasses = isAuthor ? “c-topic-link c-topic-link–author” : “c-topic-link”; return [ ” “, ].join(“”); } /** * Generates story card markup * @param {Object} article – to display * @param {Object} topicData – (topicName, topicSlug, topicType, topicVariation, topicImg) * @param {Boolean} addFollowButton * @returns {String} story card markup */ function storyCard(article, topicData, addFollowButton) { // console.info(“[ARC-7231] storyCard”, { article: article, topic: topicData }); if (!article || !topicData) { return “”; } var tName = topicData.topicName; var tType = topicData.topicType; var tVariation = topicData.topicVariation; var followingTopic; var timeTemplate; var analyticsModifier = tType + “: “; if (addFollowButton) { // Display a follow button beside the topic name followingTopic = displayFollowingButton(topicData); timeTemplate = displayDateTag(article); } var label = getLabel(article); var image = getImage(article, label); var labelTemplate = displayLabel(label); var imageTemplate = displayImage(image); var headline = article.headlines.basic; var href = window.tgam.env.baseUrl + article.canonical_url; var sophiId = article._id; var dataAnalyticsClick = JSON.stringify({ type: “link”, feature: “following feed”, contentId: sophiId, label: analyticsModifier + tName.toLowerCase() + “: ” + headline.toLowerCase(), page: “sec:homepage:personalized feed:” + tVariation, hierarchy: 1 }); var cardMarkup = “”; if (!followingTopic) { cardMarkup = [ “”, ” “, ”

“, ” “, tName, “”, ”

“, ”

“, ” “, headline, “”, ”

“, labelTemplate, ” “, ”

“, imageTemplate, “

“, “” ].join(“”); } else { cardMarkup = [ ”

“, followingTopic, ”

“, ” “, ” “, ”

“, ” “, headline, “”, ”

“, ” “, timeTemplate, “”, ” “, ”

“, imageTemplate, “

“, ” “, ].join(“”); } return [ ”

“, cardMarkup, ”

“, ].join(“”); } /** * Adds the overlay trigger dot class * @param {String} type – “unread” or “no-follow” */ function addOverlayTriggerDot(type) { overlayTriggerDotClasses.forEach(function fn(dotClass) { if (dotClass === “c-your-globe__trigger–dot–” + type) { overlayTrigger.classList.add(dotClass); } else { overlayTrigger.classList.remove(dotClass); } }); overlayTrigger.classList.add(“c-your-globe__trigger–dot”); } /** * Removes the overlay trigger dot class */ function removeOverlayTriggerDot() { overlayTriggerDotClasses.forEach(function fn(dotClass) { overlayTrigger.classList.remove(dotClass); }); overlayTrigger.classList.remove(“c-your-globe__trigger–dot”); } /** * Returns a heading element to be displayed inside the overlay * @param {String} text * @returns {String} */ function overlayLabel(text) { return “” + text + “”; } var overlayHeadingHasFollowed = ( overlayLabel(“The latest in topics and authors you follow”) + “

View more in Following

” ); var overlayHeadingNoFollowed = ( overlayLabel(“Get started: build your personal news feed”) + “” + “

  • Follow topics relevant to your reading interests.
  • ” + “

  • Check back here or your Following page to view the latest articles on your topics.
  • ” + “” ); var upToDateMessage = “

    You’re up to date on your Following feed. Check again later for new stories.

    “; // ************************************************ // Parse API response and inject markup into overlay // ************************************************ // Story card markup /** * Stories originally came from the following locations in the API response: * – data.articles[i].items[i].topics * – data.articles[i].items[i].authors * @param {Array} stories * @returns {String} story card markup */ function latestStoryCards(stories) { console.info(“[ARC-7231] Display latest stories based on these stories:”, stories); var storyCards = stories.map(function fn(story) { // The “topics” and “authors” arrays will only contain one item // (i.e. the topic or author that the user is following) var topic; var topicData; if (story.topics && story.topics.length) { // Normal topic topic = story.topics[0]; topicData = { topicName: topic.name, topicSlug: topic.slug, topicType: “topic”, topicVariation: “following” }; } else if (story.authors && story.authors.length) { // Author topic topic = story.authors[0]; // Only authors have images associated with them – normal topics do not var authorImg = topic.metadata && topic.metadata.image ? topic.metadata.image : null; topicData = { topicName: topic.byline, topicSlug: topic.slug, topicType: “author”, topicVariation: “following”, topicImg: authorImg }; } // Don’t display a follow button beside the topic because the user is already following it return storyCard(story, topicData, false); }).join(“”); return storyCards; } /** * @param {Array} topics * @param {String} variation – “recommended” or “trending” (used for the click tracking analytics) * @returns {String} story card markup */ function recommendedTrendingStoryCards(topics, variation) { var uniqueStories = generateUniqueStory(topics); var storyCards = uniqueStories.map(function fn(topic) { // Grab one article var story = topic.items[0]; // Only authors have images associated with them – normal topics do not var authorImg = topic.authorTopic && topic.authorMetadata && topic.authorMetadata.image ? topic.authorMetadata.image : null; // Normally we’d display all of the topics that are assigned to an article, but // this API groups articles by topic, so we only have access to that one topic. // Even if we could display additional topics, we wouldn’t want to becuase having // multiple follow buttons would junk up the UI. var topicData = { topicName: topic.name, topicSlug: topic.slug, topicType: topic.authorTopic ? “author” : “topic”, topicVariation: variation, topicImg: authorImg }; // Display the follow button beside the topic because we’re suggesting new topics to follow return storyCard(story, topicData, true); }).join(“”); return storyCards; } /** * Topics originally came from the following locations in the API response: * – data.recommendedAuthors * – data.recommendedTopics * @param {Array} topics * @returns {String} story card markup */ function recommendedStoryCards(topics) { console.info(“[ARC-7231] Display recommended stories based on these topics:”, topics); return recommendedTrendingStoryCards(topics, “recommended”); } /** * Topics originally came from the following location in the API response: * – data.trendingTopics * @param {Array} topics * @returns {String} story card markup */ function trendingStoryCards(topics) { console.info(“[ARC-7231] Display trending stories based on these topics:”, topics); return recommendedTrendingStoryCards(topics, “trending”); } // Markup inside the overlay /** * @param {Array} stories * @returns {Object} markup for the overlay’s header and body content areas */ function showLatestStories(stories) { console.info(“[ARC-7231] Scenario: latest stories”); var storyCardsMarkup = latestStoryCards(stories); return { header: overlayHeadingHasFollowed, body: storyCardsMarkup }; } /** * @param {Array} topics * @returns {Object} markup for the overlay’s header and body content areas */ function upToDateShowRecommended(topics) { console.info(“[ARC-7231] Scenario: up to date, show recommended”); var storyCardsMarkup = recommendedStoryCards(topics); return { header: overlayHeadingHasFollowed, body: ( upToDateMessage + overlayLabel(“Recommended for you”) + storyCardsMarkup ) }; } /** * @param {Array} topics * @returns {Object} markup for the overlay’s header and body content areas */ function upToDateShowTrending(topics) { console.info(“[ARC-7231] Scenario: up to date, show trending”); var storyCardsMarkup = trendingStoryCards(topics); return { header: overlayHeadingHasFollowed, body: ( upToDateMessage + overlayLabel(“Trending topics to follow”) + storyCardsMarkup ) }; } /** * @param {Array} topics * @returns {Object} markup for the overlay’s header and body content areas */ function notFollowingShowRecommended(topics) { console.info(“[ARC-7231] Scenario: not following, show recommended”); var storyCardsMarkup = recommendedStoryCards(topics); return { header: overlayHeadingNoFollowed, body: ( overlayLabel(“Recommended for you”) + storyCardsMarkup ) }; } /** * @param {Array} topics * @returns {Object} markup for the overlay’s header and body content areas */ function notFollowingShowTrending(topics) { console.info(“[ARC-7231] Scenario: not following, show trending”); var storyCardsMarkup = trendingStoryCards(topics); return { header: overlayHeadingNoFollowed, body: ( overlayLabel(“Trending topics to follow”) + storyCardsMarkup ) }; } /** * Parse data from the personalized API and inject markup into the overlay * @see https://confluence.theglobeandmail.com/display/ARC/Logic+for+Embedded+on+Homepage++and+Your+Globe+Overlay * @param {Object} data – topic and story data provided by the API * @param {String} hashId – user’s hash id */ function parsePerzonalizedTopicsData(data, hashId) { console.info(“[ARC-7231] parsePerzonalizedTopicsData”, data); var totalTopicsFollowed = data.totalTopicsFollowed || 0; var totalAuthorsFollowed = data.totalAuthorsFollowed || 0; var recommendedTopics = data.recommendedTopics || []; var recommendedAuthors = data.recommendedAuthors || []; var latestStories = data.articles || []; var topics = []; var stories = []; var markup = “”; if (totalTopicsFollowed || totalAuthorsFollowed) { if (latestStories.length) { // Scenario 1: “Latest stories” // Count the number of stories returned (for logging/debugging purposes only) var latestStoriesCount = latestStories.reduce(function _reduceStories(accumulator, date) { var urls = date.items.map(function _mapStories(article) { return article.canonical_url; }); return accumulator.concat(urls); }, []).length; console.info(“[ARC-7231] latestStoryUrls (” + latestStoriesCount + “)”); // Fetch the user’s reading history // TODO: this API request will no longer be necessary when Data Science makes // the “isRead” property functional (it’s currently “false” 100% of the time) getReadingHistory(hashId).then(function _historyFetched(historyData) { var readingHistoryUrls = historyData.map(function _mapHistory(item) { return item.url; }); console.info(“[ARC-7231] readingHistoryUrls (” + readingHistoryUrls.length + “)”); var currentArticleUrl = window.tgam.meta.pagetype === “story” ? window.tgam.meta.urlRelative : null; // Filter out stories that exist in the user’s reading history var filteredStories = latestStories.map(function _mapDates(dateObj) { var items = dateObj.items.filter(function _filterStories(article) { var articleUrl = article.canonical_url; var shouldRemove = readingHistoryUrls.includes(articleUrl) || article.isRead || articleUrl === currentArticleUrl; if (shouldRemove) { if (articleUrl === currentArticleUrl) { console.info(“[ARC-7231] Currently reading this article, so removing: ” + articleUrl); } else { console.info(“[ARC-7231] Has already been read, so removing: ” + articleUrl); } } return !shouldRemove; }); return { date: dateObj.date, items: items }; }, []); stories = generateLatestStories(filteredStories); markup = showLatestStories(stories); var atLeastOneStoryIsNew = isLocalStorageSupported() ? checkNewStories(stories) : true; if (atLeastOneStoryIsNew) { // Display indicator only when there is a new story since the last time the user checked the feed addOverlayTriggerDot(“unread”); } populateOverlay(markup, true); }); } else { if (recommendedTopics.length || recommendedAuthors.length) { // Scenario 2: “Up to date, show recommended” topics = recommendedAuthors.concat(recommendedTopics); markup = upToDateShowRecommended(topics); } else { // Scenario 3: “Up to date, show trending” topics = data.trendingTopics || []; markup = upToDateShowTrending(topics); } populateOverlay(markup, true); } } else { topics = recommendedAuthors.concat(recommendedTopics); if (topics.length) { // Scenario 4: “Not following, show recommended” markup = notFollowingShowRecommended(topics); } else { // Scenario 5: “Not following, show trending” topics = data.trendingTopics || []; markup = notFollowingShowTrending(topics); } addOverlayTriggerDot(“no-follow”); populateOverlay(markup, false); } } /** * Populate the overlay with content and activate the “following” functionality * @param {String} markup – HTML markup * @param {Boolean} headerBorder – whether to include a header border */ function populateOverlay(markup, headerBorder) { var overlayHeader = qs(“.c-your-globe__overlay-header”); var overlayHeaderText = qs(“.c-your-globe__overlay-header-text”); var overlayBody = qs(“.c-your-globe__overlay-body”); if (!overlayHeader || !overlayHeaderText || !overlayBody) { return; } console.info(“[ARC-7231] Append markup”); var spinner = qs(“.c-spinner”); spinner && spinner.parentElement.removeChild(spinner); overlayHeaderText.insertAdjacentHTML(“afterbegin”, markup.header); overlayBody.insertAdjacentHTML(“afterbegin”, markup.body); if (!headerBorder) { overlayHeader.classList.add(“c-your-globe__overlay-header–no-border”); } addFollowingFunctionality(); } // ************************************************ // API calls // ************************************************ // Reading History API /** * Validate a response has an “ok” status, and is in the range 200-299 inclusive. * @param {Response} response – to validate * @returns {Promise

    Leave a Reply