Video by via Dailymotion Source महायुद्ध Live: कॉंग्रेसमध्ये नेमकं काय चाललंय? Maharashtra Congress | Nana Patole vs Balasaheb Thorat Mahayudha live with Ashish Jadhao #Congress #NanaPatole #BalasahebThoratSubscribe to Our Channel https://www.youtube.com/user/LokmatNews?sub_confirmation=1 आमचा video आवडल्यास धन्यवाद. Like, Share and Subscribe करायला विसरू नका! मित्रांसोबत गप्पा मारताना विश्वसनीय, संशोधनावर आधारीत माहिती सादर करायची असेल तर लोकमतचे चॅनल…
Author: Michael G
Titanic Movie Clip – Open Your Eyes
Video by via Dailymotion Source Titanic Movie Clip – Open Your Eyes – US Release Date: February 9, 2023Starring: Billy Zane, Kate Winslet, Leonardo DiCaprioDirector: James CameronSynopsis: James Cameron’s “Titanic” is an epic, action-packed romance set against the ill-fated maiden voyage of the R.M.S. Titanic; the pride and joy of the White Star Line and,…
Pixel Lab Photo Editing | Photo per Shayari Kaise Likhen | Photo Editing App
Pixel Lab Photo Editing | Photo per Shayari Kaise Likhen | Photo Editing App
full video link
https://dai.ly/x8i23ap
follow me https://www.instagram.com/pro__shahnawaz/
Playlist
12 – Mobile Tripod Gimbal Shots https://dailymotion.com/playlist/x7p6oo
hashtag
#proshahnawaz #sadshayri #photoparshyrikaiselikhen #photoediting
A time warp 1974 Vauxhall Victor FE with just 86 miles on the clock has been discovered in a…
The classic motor was bought brand new but was virtually unused by its proud owner, known only as Mr Milner.
Before the pristine car was locked away in an outbuilding, its moss green body work was oiled and the seats covered in polythene.
Bizarrely, a dozen empty red fuel cannisters along with a 1974 Haynes manual was put in the boot.
The car was found locked in a garage following Mr Milner’s death around ten years ago.
After being sold to a collector by the executors of Mr Milner’s estate, it was bought by The Great British Car Journey museum in Ambergate, Derbys., last November.
Staff have now posted pictures of the car on Facebook in a bid to discover more about its history and the mysterious Mr Milner.
Documents found in the glove box show Mr Milner bought the car from Mercury Garage, in Ilkeston, Derbys., on April 12, 1974.
Six years after the car was purchased, Mr Milner took it to Derby for Ziebart rust proofing.
It then had its cream leather seats covered in protective wrapping and a number of spare parts, including an exhaust pipe and fuel cans, put in the boot.
The car is thought to have sat untouched for decades before it was finally unearthed during a house clearance following Mr Milner’s death.
Richard Felkin, who bought the car from Mr Milner’s estate, said: “The car was originally found by Dez Dexter who does demolition work – we buy all the reclaimed bricks off him.
“He was asked to clear this land by the executor of the will for Mr Milner when he passed but he didn’t know the car was there.
“I was collecting bricks and ended up buying the car off him.
“When I found the car, all the chrome and lights had been removed and stored in the car.
“What couldn’t be removed was covered over to protect it.”
With no family or friends to ask, the museum is hoping those who lived nearby at the time may be able to provide some information about the car’s history.
The car has the registration plate SRB 705M and has a top speed of 110mph.
Museum founder Richard Usher said: “We would love to know more about this Victor and why the owner never used it.
“It really is a one of a kind story that we’re desperate to know more about.
“If the name of Mr Milner or the car description rings any bells, please get in touch with us as we would love to solve the puzzle of this mystery car.”
‘Share your Moodle love 🧡🎓’ competition: only 1 week left to vote
Hello Moodlers!
Are we in the Moodle for love?
We now have 14 brilliant entries for the ‘Share your Moodle love 🧡🎓’ competition. There’s one week left to vote!
We’d like you to vote for the Moodle course design(s) that you love. You have until Monday 13 January 2023 at 23:59 UTC to vote for a great course, and we have a prize for the winner and runner-up (and badges) to be announced on 14th February 2023.
Head to the Competition Centre to read the rules and vote for your favourite Moodle course design, now.
Note: you need to self-enrol in the Competition Centre and remain enrolled for your vote to count! Vote are on each single entry (not in ‘list view).
Best wishes and good luck to all the 14 great entries!
Aurélie and the Community Sites team
Specbee: Taming JavaScript in Drupal (Includes FAQs)
Sagar Chauhan
07 Feb, 2023
Interactive web experiences provide a more engaging and enjoyable experience for users. It leads to increased user satisfaction and a positive perception of a website. For example, a form that provides instant feedback and validation, rather than making the user wait for a page refresh, can significantly improve the user experience.
JavaScript plays an important role in Drupal by providing the means to create dynamic and interactive experiences for users on the frontend of a Drupal website. It enables developers to modify the behavior of certain elements on a page, such as forms, links, or any other DOM elements, without having to refresh the entire page. Drupal Behaviors are JavaScript functions that get executed when specific events occur on a page. Behaviors make it easy for developers to maintain and upgrade a site as they don’t need to change any underlying HTML code. Find out all you wanted to know about Drupal Behaviors in the article.
What are Drupal Behaviors?
Drupal.behaviors is an object inside the Javascript structure in Drupal, which allows us to attach functions to be executed at certain times during the execution of the application. It is called when the DOM is fully loaded, but these behaviors can be called again. Drupal’s official JavaScript documentation suggests that modules should implement JavaScript by attaching logic to Drupal.behaviors.
Why do we need Drupal behaviors?
The advantage of Behaviors is that they are automatically re-applied to any content that is loaded through AJAX. They can be called at any time with a context that represents new additions or changes to the DOM. This is better than $(document).ready() or document DOMContentLoaded where the code is just run once.
When are Drupal behaviors unwanted?
Drupal behaviors are not always the perfect solution for writing Javascript in Drupal. In some cases, as stated below Drupal behaviors are not needed at all!
- When we need to execute some code that does not affect the DOM. Eg. Initializing an external script like Google Analytics
- When some JS operation needs to be performed on the DOM just once knowing that the element will be available when the page loads (This scenario is different from using Once).
When are Drupal Behaviors called?
- After an administration overlay has been loaded into the page.
- After the AJAX Form API has submitted a form.
- When an AJAX request returns a command that modifies the HTML, such as ajax_command_replace().
Other times when Drupal Behaviors are invoked
- CTools calls it after a modal has been loaded.
- Media calls it after the media browser has been loaded.
- Panels calls it after in-place editing has been completed.
- Views calls it after loading a new page that uses AJAX.
- Views Load More calls it after loading the next chunk of items.
- JavaScript from custom modules may call Drupal.attachBehaviors() when they add or change parts of the page.
Writing code without Drupal behaviors
In this code, we are adding a click event listener to the .views-row class which calculates the number of times we are clicking on this row. But it is added only once to the elements which come in the DOM during the initial page load. After clicking on Load More and loading more items, the click listener does not work on the newly loaded items.
// No Drupal Behaviors
(function () {
let header = document.querySelector(".food-list-header");
if (header) {
let greatFoodSpan = document.createElement("span");
greatFoodSpan.textContent = "Get ready for great food!!!!!!";
header.append(greatFoodSpan);
}
// Add the event listener for each click on the food
let foods = document.querySelectorAll(".views-row");
foods.forEach((food) => {
food.addEventListener("click", () => {
let foodCounter = food.querySelector(".food-click-counter");
let timesClicked = parseInt(foodCounter.textContent.trim());
foodCounter.textContent = ++timesClicked;
});
});
})();
How do we use Drupal Behaviors?
Answer: Using the attach method
Things to remember:
- The new object needs to have at least an attach method.
- Anytime Drupal.attachBehaviors is called, it will iterate through all behavior objects and call their respective attach methods.
Adding Drupal behavior to our code
After adding Drupal Behaviors, the code looks something like this.
(function (Drupal) {
Drupal.behaviors.exampleBehaviour1 = {
attach: (context, settings) => {
// Add a delicious text to the top of the document
let header = document.querySelector(".food-list-header");
// jQuery Equivalent
// $(".food-list-header");
if (header) {
let greatFoodSpan = document.createElement("span");
greatFoodSpan.textContent = "Get ready for great food!!!!!!";
header.append(greatFoodSpan);
}
// Add the event listener for each click on the food
let foods = document.querySelectorAll(".views-row");
foods.forEach((food) => {
food.addEventListener("click", () => {
let foodCounter = food.querySelector(".food-click-counter");
let timesClicked = parseInt(foodCounter.textContent.trim());
foodCounter.textContent = ++timesClicked;
});
});
},
};
})(Drupal);
But something odd appears in the top when we click on Load More:
This is because Drupal behavior is called a lot of times and subsequently we get some unintended behavior.
What is Context in “Drupal context”?
- When calling the attach method for all behaviors, Drupal passes along a context parameter.
- The context parameter that is passed can often give a better idea of what DOM element is being processed.
- During the initial page load this will be the complete HTML Document; during subsequent calls, this will be just the elements that are being added to the page or get modified.
How to add Context?
The previous problem can be solved by using the context parameter that is provided by Drupal Behaviors. In this case, the first time the page loads, we get the whole HTML Document as context and that’s when we attach the header. For further operations, it will be the part of the code which is affected by Drupal Behaviors and hence that part of the code is safely controlled.
(function (Drupal) {
Drupal.behaviors.exampleBehaviour2 = {
attach: (context, settings) => {
// Add a delicious text to the top of the document.
// The context parameter now can be used for adding
// certain functionality which removes unwanted repeatability
let header = context.querySelector(".food-list-header");
// jQuery Equivalent
// $(".food-list-header", context);
if (header) {
let greatFoodSpan = document.createElement("span");
greatFoodSpan.textContent = "Get ready for great food!!!!!!";
header.append(greatFoodSpan);
}
// Add the event listener for each click on the food
let foods = context.querySelectorAll(".views-row");
foods.forEach((food) => {
food.addEventListener("click", () => {
let foodCounter = food.querySelector(".food-click-counter");
let timesClicked = parseInt(foodCounter.textContent.trim());
foodCounter.textContent = ++timesClicked;
});
});
},
};
})(Drupal);
Again there is some odd behavior when we click on Load More. The food items which were initially loaded work fine. But After clicking on Load More, the new items get the click listener and work normally. But the initially loaded items get the listener attached again and clicking on them calls the click event more than once!
When do Drupal Behaviors start misbehaving?
- Writing all the event listeners inside Drupal behaviors without using Once and Context.
- Declaring unwanted functions inside Drupal behaviors which leads to the redeclaration of functions every time the attach method is called.
“Once” to the rescue
- Once ensures that something is processed only once by adding a data-once attribute in a DOM element after the code has been executed.
- If the behavior is called again, the element with the data-once attribute is skipped for further execution.
- Once is a modern implementation of jQuery.once (which is an endeavor to move away from jQuery)
- Once, in combination with context, controls the entire functionality perfectly as we need it.
Adding Once to fix the event listeners in our code
(function (Drupal, once) {
Drupal.behaviors.exampleBehaviour3 = {
attach: (context, settings) => {
once("food-header-initialized", ".food-list-header", context).forEach(
(header) => {
let greatFoodSpan = document.createElement("span");
greatFoodSpan.textContent = "Get ready for great food!!!!!!";
header.append(greatFoodSpan);
}
);
// jQuery Equivalent
// $(".food-list-header", context).once("food-header-initialized", function (header) {
//
// });
// Add the event listener for each click on the food
once("food-initialized", ".views-row", context).forEach((food) => {
food.addEventListener("click", () => {
let foodCounter = food.querySelector(".food-click-counter");
let timesClicked = parseInt(foodCounter.textContent.trim());
foodCounter.textContent = ++timesClicked;
});
});
},
};
})(Drupal, once);
Now everything works as intended. We get a data-once attribute to the elements where the event listeners are attached and newly loaded elements and previously loaded elements function properly.
The Need for Detach method
The Detach method acts like an anti-hero (not evil), removing whatever we did in the attach method. Any code in the detach method will be called whenever content is removed from the DOM. This helps us to clean up our application. For example, Detach method enables us to remove unwanted event listeners which consume resources like a continuous polling situation.
Examples of Detach
Assume that we have an ajax form to fill and we are using a timer to show the time elapsed. We use setTimeOut to manage the timer. We log this timer in the console for monitoring.
(function (Drupal, once) {
let counter = 0;
Drupal.behaviors.exampleBehaviour4 = {
attach: (context, settings) => {
once("timer-initalized", ".contact-timer", context).forEach((ele) => {
const timer = context.querySelector(".contact-timer-sec");
timer.textContent = counter;
// Set the timer for user to see the time elapsed
setInterval(() => {
console.log("This is logging");
const timer = document.querySelector(".contact-timer-sec");
timer.textContent = ++counter;
}, 1000);
});
},
};
})(Drupal, once);
On form submission, the timer on DOM gets removed but the console starts throwing an error. This is because the element on which the setTimeOut is acting has been removed from DOM:
To avoid this we can use the detach method like this:
(function (Drupal, once) {
let counter = 0;
let intervalStopper;
Drupal.behaviors.exampleBehaviour4 = {
attach: (context, settings) => {
// Set the timer for user to see the time elapsed
once("timer-initialized", ".contact-timer", context).forEach((ele) => {
const timer = context.querySelector(".contact-timer-sec");
timer.textContent = counter;
intervalStopper = setInterval(() => {
const timer = document.querySelector(".contact-timer-sec");
timer.textContent = ++counter;
console.log("This is logging");
}, 1000);
});
},
// Clear the timer on confirmation
detach: (context, settings, trigger) => {
const timer = context.querySelector(".contact-timer-sec");
if (trigger == "unload" && timer) {
clearInterval(intervalStopper);
}
},
};
})(Drupal, once);
This removes the timer on unload and as seen from the logger, the error does not occur.
Immediately Invoked Function Expressions (IIFE) – The wrapper for JS
We have been using IIFE to write our Drupal code. The initial opening parentheses define an anonymous function which helps prevent the function’s scope from polluting the global scope of the entire application. You can pass arguments to your anonymous function by including them as arguments at the end of the function definition.
This also helps us to namespace the parameters however we want them to be used.
Example:
// Function name crisis!!!!
// The function is vulnearble to
// be replaced by some other function
function someFunction() {
// Some code for this function
}
(function (Drupal) {
// Function name crisis averted!
function someFunction() {
// Some code for this other function
}
Drupal.behaviors.exampleBehaviour6 = {
attach: (context, settings) => {
someFunction();
},
};
})(Drupal);
Final Thoughts
Implementing Drupal behaviors allows for dynamic interactivity, streamlined user interaction, improved user feedback, efficient development and overall enhanced user experience of your website. Drupal.behaviors are flexible and modular, in that they can be executed multiple times on a page, can override and extend existing behavior, and can be automatically re-applied to any content loaded through Ajax.
Looking for a Drupal development agency to help you build interactive web experiences, making the best out of Drupal? We’d love to talk!