1671687319
Among the most famous and long-lived online platforms are those for blogging. From the very beginning, people from all paths of life have found a special space to communicate with others in them. One of the best things is that in this current era, the options at your disposal are huge.
For example, you are not restricted to post only about something popular/commercial, nor to use only words.
The variety is huge, and if it is not clear to you by now, blogging as a business model is very important as well. And again, even to get paid you have so much flexibility nowadays.
Given the salience of blogging, in this article, we will talk about 6 of the most popular free blogging sites. We will mention its options to choose from, major appeals, and more.
WordPress is the biggest website builder ever created, around 40% of the web is built on it!
The magic of it is the flexibility you get; you can make your website about anything. And knowing how to code is not necessary!
It has great themes and customization tools to make your website stand out. Plus, you and your visitors will see a nice mobile version.
The free version misses the 50k plugins, advanced SEO, integrations, and others. But you can still register a new domain, connect your email, use the customization tool, etc.
Let me guide you through its theme to illustrate its variety for you. For the free version, there are 4 categories for layouts and 5 distinct features. Also, 5 subjects (e.g., art, blog, business) and 5 main styles.
You can choose from every one of these categories and in total, you got +70 templates. Every template also has several formats to choose from. Plus, there is an open live demo for anyone on the web.
There are reasons why WordPress is where it is right now and above rest a few.
Wix is one of the first ideas you get thinking of creating a website/blog. It keeps up with its competition and offers great customization, features, and accessibility. You can make a professional-looking page without knowing how to code with ease as well.
Its major appeal is that it has a bigger range of templates and it has a drag-and-drop system for customization. Plus, for those with limited time, there is an AI that makes your website fast after answering a few quick questions.
The free version has 100 templates, unlimited pages, and top-grade hosting. Plus, you can also customize your domain, add categories, hashtags, and schedule posting. Also, its presentation is great for mobiles.
The templates count with many categories. For blogging alone, there are 25 templates. With 8 subcategories: personal, food and travel, news and business, arts, fashion and beauty, sports and wellness, and podcasts.
Its editor is from a next-level kind: advance, precise, and complete. It counts with 5 tools, 9 main sections for elements addition. Plus, there is the option to check the mobile version with one click.
As its name suggests, it is only for blogs. It is completely integrated with Google services as it was bought by them in 2003. You get a free domain, flexible templates, stats, and counts with Google AdSense by default.
The interface as you can imagine is very different from those 2 above. It is more simple and not so colorful, those familiar with the open-source world will find many similarities. That is not to say it is bad or not that good, it is simply different.
As for the themes, there are 12 main categories with 49 themes in total, and customization is limited. You can change the background image, fonts, and color for each section. Plus, there is a preview that lets you check the mobile version in one click as well. As for the Layouts, there are 7 sections in which you can select and customize some gadgets.
The post creator is also simple, it counts with basic writing options. Plus, you can add links, multimedia, and special characters. The post that you’re working on is in the cloud and updates constantly. Remarkable is that you can customize the permalink of your posts.
And there is a separate section dedicated only to comments, stats, earnings, and others.
It is an advanced website creator, bought by Squarespace in 2018, that competes with Wix in the customization front.
Its free plan counts with 500Mb storage, domain customization, lead capture, and contact forms. Plus, the usual basic SEO optimization, community forums, security, and support standards.
On themes, for blogging alone there are 6 themes. Its editor is very complete with 18 individual elements. 3 of them are premium (audio player, search box, and HD video). There are tons of forms, flashes, also fonts, and theme colors.
Something remarkable is its app center with 56 free apps with different functions to choose from. They count with a rating system, so you’ll know where to focus on. Also, it is remarkable that you can add and create groups, members, and editors in the free plan.
Medium with its focus on content and +170M readers takes a different approach. It is a type of marketplace for written posts of all kinds of topics and in all styles. The number of topics and subtopics on the platform is overwhelming, so there is space for anyone.
As for customization, it is restricted. There is no theme to choose from. And what you can do is customize the logo, accent, background, layouts, fonts, and color. Its editor is simple but complete, like Blogger’s, there isn’t much one could miss from it.
Remarkably, you count with newsletters, a space for discussion engagement with your followers, as well as stats and mobile app.
Lastly, to make money you have to get in its partner program which is free and pays based on reading time.
Last but not least is Tumblr, one of the biggest names online as its +520M posts can testify. Though the site says to be all about blogging, it is mostly about all types of content about all topics and styles/formats.
Customization is also limited, there is no theme you can choose, nor can you change colors or fonts. What you can do is to post text, photos, audio, videos, links, quotes, etc. Think of Twitter.
After a very brief analysis of the page, there are a few pieces of advice I could give you. First, texts and art are not trending, though the latter gets selected often in the staff pics. Second, most of the written content is based on takes and thoughts, with a tone similar to Twitter’s). Third, unfortunately, the site is not very organized and what gets the attention is not blogging.
But, that is not to say that you could not be a traditional blogger and find your space in there. Certainly, in such a huge platform there will always be niches. Only bear in mind that Tumblr is not aimed at that type of content and that other sites do.
To conclude, allow me to mention a few words on each platform we talked about here.
WordPress is huge and has a good number of themes but lacks some customization. Wix stands out for its customization and number of themes.
Blogger is a simpler site appropriate for bloggers that value minimalism and content.
Weebly, in turn, lacks in the number of themes but makes up with higher customization and features. Which makes it compete with Wix.
Medium, is a one-of-a-kind platform, a marketplace for ideas, attractive for all writers. Tumblr offers a different space for content creators, one that looks like a social media site.
Thanks for reading this article, we hope it has been insightful and useful.
Original article source at: https://www.blog.duomly.com/
1635917640
このモジュールでは、Rustでハッシュマップ複合データ型を操作する方法について説明します。ハッシュマップのようなコレクション内のデータを反復処理するループ式を実装する方法を学びます。演習として、要求された注文をループし、条件をテストし、さまざまなタイプのデータを処理することによって車を作成するRustプログラムを作成します。
錆遊び場は錆コンパイラにブラウザインタフェースです。言語をローカルにインストールする前、またはコンパイラが利用できない場合は、Playgroundを使用してRustコードの記述を試すことができます。このコース全体を通して、サンプルコードと演習へのPlaygroundリンクを提供します。現時点でRustツールチェーンを使用できない場合でも、コードを操作できます。
Rust Playgroundで実行されるすべてのコードは、ローカルの開発環境でコンパイルして実行することもできます。コンピューターからRustコンパイラーと対話することを躊躇しないでください。Rust Playgroundの詳細については、What isRust?をご覧ください。モジュール。
このモジュールでは、次のことを行います。
Rustのもう1つの一般的なコレクションの種類は、ハッシュマップです。このHashMap<K, V>
型は、各キーK
をその値にマッピングすることによってデータを格納しますV
。ベクトル内のデータは整数インデックスを使用してアクセスされますが、ハッシュマップ内のデータはキーを使用してアクセスされます。
ハッシュマップタイプは、オブジェクト、ハッシュテーブル、辞書などのデータ項目の多くのプログラミング言語で使用されます。
ベクトルのように、ハッシュマップは拡張可能です。データはヒープに格納され、ハッシュマップアイテムへのアクセスは実行時にチェックされます。
次の例では、書評を追跡するためのハッシュマップを定義しています。ハッシュマップキーは本の名前であり、値は読者のレビューです。
use std::collections::HashMap;
let mut reviews: HashMap<String, String> = HashMap::new();
reviews.insert(String::from("Ancient Roman History"), String::from("Very accurate."));
reviews.insert(String::from("Cooking with Rhubarb"), String::from("Sweet recipes."));
reviews.insert(String::from("Programming in Rust"), String::from("Great examples."));
このコードをさらに詳しく調べてみましょう。最初の行に、新しいタイプの構文が表示されます。
use std::collections::HashMap;
このuse
コマンドは、Rust標準ライブラリの一部HashMap
からの定義をcollections
プログラムのスコープに取り込みます。この構文は、他のプログラミング言語がインポートと呼ぶものと似ています。
HashMap::new
メソッドを使用して空のハッシュマップを作成します。reviews
必要に応じてキーと値を追加または削除できるように、変数を可変として宣言します。この例では、ハッシュマップのキーと値の両方がString
タイプを使用しています。
let mut reviews: HashMap<String, String> = HashMap::new();
このinsert(<key>, <value>)
メソッドを使用して、ハッシュマップに要素を追加します。コードでは、構文は<hash_map_name>.insert()
次のとおりです。
reviews.insert(String::from("Ancient Roman History"), String::from("Very accurate."));
ハッシュマップにデータを追加した後、get(<key>)
メソッドを使用してキーの特定の値を取得できます。
// Look for a specific review
let book: &str = "Programming in Rust";
println!("\nReview for \'{}\': {:?}", book, reviews.get(book));
出力は次のとおりです。
Review for 'Programming in Rust': Some("Great examples.")
ノート
出力には、書評が単なる「すばらしい例」ではなく「Some( "すばらしい例。")」として表示されていることに注意してください。get
メソッドはOption<&Value>
型を返すため、Rustはメソッド呼び出しの結果を「Some()」表記でラップします。
この.remove()
メソッドを使用して、ハッシュマップからエントリを削除できます。get
無効なハッシュマップキーに対してメソッドを使用すると、get
メソッドは「なし」を返します。
// Remove book review
let obsolete: &str = "Ancient Roman History";
println!("\n'{}\' removed.", obsolete);
reviews.remove(obsolete);
// Confirm book review removed
println!("\nReview for \'{}\': {:?}", obsolete, reviews.get(obsolete));
出力は次のとおりです。
'Ancient Roman History' removed.
Review for 'Ancient Roman History': None
このコードを試して、このRustPlaygroundでハッシュマップを操作できます。
演習:ハッシュマップを使用して注文を追跡する
この演習では、ハッシュマップを使用するように自動車工場のプログラムを変更します。
ハッシュマップキーと値のペアを使用して、車の注文に関する詳細を追跡し、出力を表示します。繰り返しになりますが、あなたの課題は、サンプルコードを完成させてコンパイルして実行することです。
この演習のサンプルコードで作業するには、次の2つのオプションがあります。
ノート
サンプルコードで、
todo!
マクロを探します。このマクロは、完了するか更新する必要があるコードを示します。
最初のステップは、既存のプログラムコードを取得することです。
car_quality
、car_factory
およびmain
機能を。次のコードをコピーしてローカル開発環境で編集する
か、この準備されたRustPlaygroundでコードを開きます。
#[derive(PartialEq, Debug)]
struct Car { color: String, motor: Transmission, roof: bool, age: (Age, u32) }
#[derive(PartialEq, Debug)]
enum Transmission { Manual, SemiAuto, Automatic }
#[derive(PartialEq, Debug)]
enum Age { New, Used }
// Get the car quality by testing the value of the input argument
// - miles (u32)
// Return tuple with car age ("New" or "Used") and mileage
fn car_quality (miles: u32) -> (Age, u32) {
// Check if car has accumulated miles
// Return tuple early for Used car
if miles > 0 {
return (Age::Used, miles);
}
// Return tuple for New car, no need for "return" keyword or semicolon
(Age::New, miles)
}
// Build "Car" using input arguments
fn car_factory(order: i32, miles: u32) -> Car {
let colors = ["Blue", "Green", "Red", "Silver"];
// Prevent panic: Check color index for colors array, reset as needed
// Valid color = 1, 2, 3, or 4
// If color > 4, reduce color to valid index
let mut color = order as usize;
if color > 4 {
// color = 5 --> index 1, 6 --> 2, 7 --> 3, 8 --> 4
color = color - 4;
}
// Add variety to orders for motor type and roof type
let mut motor = Transmission::Manual;
let mut roof = true;
if order % 3 == 0 { // 3, 6, 9
motor = Transmission::Automatic;
} else if order % 2 == 0 { // 2, 4, 8, 10
motor = Transmission::SemiAuto;
roof = false;
} // 1, 5, 7, 11
// Return requested "Car"
Car {
color: String::from(colors[(color-1) as usize]),
motor: motor,
roof: roof,
age: car_quality(miles)
}
}
fn main() {
// Initialize counter variable
let mut order = 1;
// Declare a car as mutable "Car" struct
let mut car: Car;
// Order 6 cars, increment "order" for each request
// Car order #1: Used, Hard top
car = car_factory(order, 1000);
println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
// Car order #2: Used, Convertible
order = order + 1;
car = car_factory(order, 2000);
println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
// Car order #3: New, Hard top
order = order + 1;
car = car_factory(order, 0);
println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
// Car order #4: New, Convertible
order = order + 1;
car = car_factory(order, 0);
println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
// Car order #5: Used, Hard top
order = order + 1;
car = car_factory(order, 3000);
println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
// Car order #6: Used, Hard top
order = order + 1;
car = car_factory(order, 4000);
println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
}
2. プログラムをビルドします。次のセクションに進む前に、コードがコンパイルされて実行されることを確認してください。
次の出力が表示されます。
1: Used, Hard top = true, Manual, Blue, 1000 miles
2: Used, Hard top = false, SemiAuto, Green, 2000 miles
3: New, Hard top = true, Automatic, Red, 0 miles
4: New, Hard top = false, SemiAuto, Silver, 0 miles
5: Used, Hard top = true, Manual, Blue, 3000 miles
6: Used, Hard top = true, Automatic, Green, 4000 miles
現在のプログラムは、各車の注文を処理し、各注文が完了した後に要約を印刷します。car_factory
関数を呼び出すたびにCar
、注文の詳細を含む構造体が返され、注文が実行されます。結果はcar
変数に格納されます。
お気づきかもしれませんが、このプログラムにはいくつかの重要な機能がありません。すべての注文を追跡しているわけではありません。car
変数は、現在の注文の詳細のみを保持しています。関数car
の結果で変数が更新されるたびcar_factory
に、前の順序の詳細が上書きされます。
ファイリングシステムのようにすべての注文を追跡するために、プログラムを更新する必要があります。この目的のために、<K、V>ペアでハッシュマップを定義します。ハッシュマップキーは、車の注文番号に対応します。ハッシュマップ値は、Car
構造体で定義されているそれぞれの注文の詳細になります。
main
関数の先頭、最初の中括弧の直後に次のコードを追加します{
。// Initialize a hash map for the car orders
// - Key: Car order number, i32
// - Value: Car order details, Car struct
use std::collections::HashMap;
let mut orders: HashMap<i32, Car> = HashMap;
2. orders
ハッシュマップを作成するステートメントの構文の問題を修正します。
ヒント
ハッシュマップを最初から作成しているので、おそらくこの
new()
メソッドを使用することをお勧めします。
3. プログラムをビルドします。次のセクションに進む前に、コードがコンパイルされていることを確認してください。コンパイラからの警告メッセージは無視してかまいません。
次のステップは、履行された各自動車注文をハッシュマップに追加することです。
このmain
関数では、car_factory
車の注文ごとに関数を呼び出します。注文が履行された後、println!
マクロを呼び出して、car
変数に格納されている注文の詳細を表示します。
// Car order #1: Used, Hard top
car = car_factory(order, 1000);
println!("{}: {}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
...
// Car order #6: Used, Hard top
order = order + 1;
car = car_factory(order, 4000);
println!("{}: {}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
新しいハッシュマップで機能するように、これらのコードステートメントを修正します。
car_factory
関数の呼び出しは保持します。返された各Car
構造体は、ハッシュマップの<K、V>ペアの一部として格納されます。println!
マクロの呼び出しを更新して、ハッシュマップに保存されている注文の詳細を表示します。main
関数で、関数の呼び出しcar_factory
とそれに伴うprintln!
マクロの呼び出しを見つけます。// Car order #1: Used, Hard top
car = car_factory(order, 1000);
println!("{}: {}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
...
// Car order #6: Used, Hard top
order = order + 1;
car = car_factory(order, 4000);
println!("{}: {}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
2. すべての自動車注文のステートメントの完全なセットを次の改訂されたコードに置き換えます。
// Car order #1: Used, Hard top
car = car_factory(order, 1000);
orders(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
// Car order #2: Used, Convertible
order = order + 1;
car = car_factory(order, 2000);
orders(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
// Car order #3: New, Hard top
order = order + 1;
car = car_factory(order, 0);
orders(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
// Car order #4: New, Convertible
order = order + 1;
car = car_factory(order, 0);
orders(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
// Car order #5: Used, Hard top
order = order + 1;
car = car_factory(order, 3000);
orders(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
// Car order #6: Used, Hard top
order = order + 1;
car = car_factory(order, 4000);
orders(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
3. 今すぐプログラムをビルドしようとすると、コンパイルエラーが表示されます。<K、V>ペアをorders
ハッシュマップに追加するステートメントに構文上の問題があります。問題がありますか?先に進んで、ハッシュマップに順序を追加する各ステートメントの問題を修正してください。
ヒント
orders
ハッシュマップに直接値を割り当てることはできません。挿入を行うにはメソッドを使用する必要があります。
プログラムが正常にビルドされると、次の出力が表示されます。
Car order 1: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("Used", 1000) })
Car order 2: Some(Car { color: "Green", motor: SemiAuto, roof: false, age: ("Used", 2000) })
Car order 3: Some(Car { color: "Red", motor: Automatic, roof: true, age: ("New", 0) })
Car order 4: Some(Car { color: "Silver", motor: SemiAuto, roof: false, age: ("New", 0) })
Car order 5: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("Used", 3000) })
Car order 6: Some(Car { color: "Green", motor: Automatic, roof: true, age: ("Used", 4000) })
改訂されたコードの出力が異なることに注意してください。println!
マクロディスプレイの内容Car
各値を示すことによって、構造体と対応するフィールド名。
次の演習では、ループ式を使用してコードの冗長性を減らします。
for、while、およびloop式を使用します
多くの場合、プログラムには、その場で繰り返す必要のあるコードのブロックがあります。ループ式を使用して、繰り返しの実行方法をプログラムに指示できます。電話帳のすべてのエントリを印刷するには、ループ式を使用して、最初のエントリから最後のエントリまで印刷する方法をプログラムに指示できます。
Rustは、プログラムにコードのブロックを繰り返させるための3つのループ式を提供します。
loop
:手動停止が発生しない限り、繰り返します。while
:条件が真のままで繰り返します。for
:コレクション内のすべての値に対して繰り返します。この単元では、これらの各ループ式を見ていきます。
loop
式は、無限ループを作成します。このキーワードを使用すると、式の本文でアクションを継続的に繰り返すことができます。ループを停止させるための直接アクションを実行するまで、アクションが繰り返されます。
次の例では、「We loopforever!」というテキストを出力します。そしてそれはそれ自体で止まりません。println!
アクションは繰り返し続けます。
loop {
println!("We loop forever!");
}
loop
式を使用する場合、ループを停止する唯一の方法は、プログラマーとして直接介入する場合です。特定のコードを追加してループを停止したり、Ctrl + Cなどのキーボード命令を入力してプログラムの実行を停止したりできます。
loop
式を停止する最も一般的な方法は、break
キーワードを使用してブレークポイントを設定することです。
loop {
// Keep printing, printing, printing...
println!("We loop forever!");
// On the other hand, maybe we should stop!
break;
}
プログラムがbreak
キーワードを検出すると、loop
式の本体でアクションの実行を停止し、次のコードステートメントに進みます。
break
キーワードは、特別な機能を明らかにするloop
表現を。break
キーワードを使用すると、式本体でのアクションの繰り返しを停止することも、ブレークポイントで値を返すこともできます。
次の例はbreak
、loop
式でキーワードを使用して値も返す方法を示しています。
let mut counter = 1;
// stop_loop is set when loop stops
let stop_loop = loop {
counter *= 2;
if counter > 100 {
// Stop loop, return counter value
break counter;
}
};
// Loop should break when counter = 128
println!("Break the loop at counter = {}.", stop_loop);
出力は次のとおりです。
Break the loop at counter = 128.
私たちのloop
表現の本体は、これらの連続したアクションを実行します。
stop_loop
変数を宣言します。loop
式の結果にバインドするようにプログラムに指示します。loop
式の本体でアクションを実行します:counter
値を現在の値の2倍にインクリメントします。counter
値を確認してください。counter
値が100以上です。ループから抜け出し、
counter
値を返します。
4. もしcounter
値が100以上ではありません。
ループ本体でアクションを繰り返します。
5. stop_loop
値を式のcounter
結果である値に設定しますloop
。
loop
式本体は、複数のブレークポイントを持つことができます。式に複数のブレークポイントがある場合、すべてのブレークポイントは同じタイプの値を返す必要があります。すべての値は、整数型、文字列型、ブール型などである必要があります。ブレークポイントが明示的に値を返さない場合、プログラムは式の結果を空のタプルとして解釈します()
。
while
ループは、条件式を使用しています。条件式が真である限り、ループが繰り返されます。このキーワードを使用すると、条件式がfalseになるまで、式本体のアクションを実行できます。
while
ループは、ブール条件式を評価することから始まります。条件式がと評価されるtrue
と、本体のアクションが実行されます。アクションが完了すると、制御は条件式に戻ります。条件式がと評価されるfalse
と、while
式は停止します。
次の例では、「しばらくループします...」というテキストを出力します。ループを繰り返すたびに、「カウントが5未満である」という条件がテストされます。条件が真のままである間、式本体のアクションが実行されます。条件が真でなくなった後、while
ループは停止し、プログラムは次のコードステートメントに進みます。
while counter < 5 {
println!("We loop a while...");
counter = counter + 1;
}
for
ループは、項目のコレクションを処理するためにイテレータを使用しています。ループは、コレクション内の各アイテムの式本体のアクションを繰り返します。このタイプのループの繰り返しは、反復と呼ばれます。すべての反復が完了すると、ループは停止します。
Rustでは、配列、ベクトル、ハッシュマップなど、任意のコレクションタイプを反復処理できます。Rustはイテレータを使用して、コレクション内の各アイテムを最初から最後まで移動します。
for
ループはイテレータとして一時変数を使用しています。変数はループ式の開始時に暗黙的に宣言され、現在の値は反復ごとに設定されます。
次のコードでは、コレクションはbig_birds
配列であり、イテレーターの名前はbird
です。
let big_birds = ["ostrich", "peacock", "stork"];
for bird in big_birds
iter()
メソッドを使用して、コレクション内のアイテムにアクセスします。for
式は結果にイテレータの現在の値をバインドするiter()
方法。式本体では、イテレータ値を操作できます。
let big_birds = ["ostrich", "peacock", "stork"];
for bird in big_birds.iter() {
println!("The {} is a big bird.", bird);
}
出力は次のとおりです。
The ostrich is a big bird.
The peacock is a big bird.
The stork is a big bird.
イテレータを作成するもう1つの簡単な方法は、範囲表記を使用することですa..b
。イテレータはa
値から始まりb
、1ステップずつ続きますが、値を使用しませんb
。
for number in 0..5 {
println!("{}", number * 2);
}
このコードは、0、1、2、3、および4の数値をnumber
繰り返し処理します。ループの繰り返しごとに、値を変数にバインドします。
出力は次のとおりです。
0
2
4
6
8
このコードを実行して、このRustPlaygroundでループを探索できます。
演習:ループを使用してデータを反復処理する
この演習では、自動車工場のプログラムを変更して、ループを使用して自動車の注文を反復処理します。
main
関数を更新して、注文の完全なセットを処理するためのループ式を追加します。ループ構造は、コードの冗長性を減らすのに役立ちます。コードを簡素化することで、注文量を簡単に増やすことができます。
このcar_factory
関数では、範囲外の値での実行時のパニックを回避するために、別のループを追加します。
課題は、サンプルコードを完成させて、コンパイルして実行することです。
この演習のサンプルコードで作業するには、次の2つのオプションがあります。
ノート
サンプルコードで、
todo!
マクロを探します。このマクロは、完了するか更新する必要があるコードを示します。
前回の演習でプログラムコードを閉じた場合は、この準備されたRustPlaygroundでコードを再度開くことができます。
必ずプログラムを再構築し、コンパイラエラーなしで実行されることを確認してください。
より多くの注文をサポートするには、プログラムを更新する必要があります。現在のコード構造では、冗長ステートメントを使用して6つの注文をサポートしています。冗長性は扱いにくく、維持するのが困難です。
ループ式を使用してアクションを繰り返し、各注文を作成することで、構造を単純化できます。簡略化されたコードを使用すると、多数の注文をすばやく作成できます。
main
機能、削除次の文を。このコードブロックは、order
変数を定義および設定し、自動車の注文のcar_factory
関数とprintln!
マクロを呼び出し、各注文をorders
ハッシュマップに挿入します。// Order 6 cars
// - Increment "order" after each request
// - Add each order <K, V> pair to "orders" hash map
// - Call println! to show order details from the hash map
// Initialize order variable
let mut order = 1;
// Car order #1: Used, Hard top
car = car_factory(order, 1000);
orders.insert(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
...
// Car order #6: Used, Hard top
order = order + 1;
car = car_factory(order, 4000);
orders.insert(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
2. 削除されたステートメントを次のコードブロックに置き換えます。
// Start with zero miles
let mut miles = 0;
todo!("Add a loop expression to fulfill orders for 6 cars, initialize `order` variable to 1") {
// Call car_factory to fulfill order
// Add order <K, V> pair to "orders" hash map
// Call println! to show order details from the hash map
car = car_factory(order, miles);
orders.insert(order, car);
println!("Car order {}: {:?}", order, orders.get(&order));
// Reset miles for order variety
if miles == 2100 {
miles = 0;
} else {
miles = miles + 700;
}
}
3. アクションを繰り返すループ式を追加して、6台の車の注文を作成します。order
1に初期化された変数が必要です。
4. プログラムをビルドします。コードがエラーなしでコンパイルされることを確認してください。
次の例のような出力が表示されます。
Car order 1: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("New", 0) })
Car order 2: Some(Car { color: "Green", motor: SemiAuto, roof: false, age: ("Used", 700) })
Car order 3: Some(Car { color: "Red", motor: Automatic, roof: true, age: ("Used", 1400) })
Car order 4: Some(Car { color: "Silver", motor: SemiAuto, roof: false, age: ("Used", 2100) })
Car order 5: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("New", 0) })
Car order 6: Some(Car { color: "Green", motor: Automatic, roof: true, age: ("Used", 700) })
プログラムは現在、ループを使用して6台の車の注文を処理しています。6台以上注文するとどうなりますか?
main
関数のループ式を更新して、11台の車を注文します。 todo!("Update the loop expression to create 11 cars");
2. プログラムを再構築します。実行時に、プログラムはパニックになります!
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 1.26s
Running `target/debug/playground`
thread 'main' panicked at 'index out of bounds: the len is 4 but the index is 4', src/main.rs:34:29
この問題を解決する方法を見てみましょう。
このcar_factory
関数では、if / else式を使用color
して、colors
配列のインデックスの値を確認します。
// Prevent panic: Check color index for colors array, reset as needed
// Valid color = 1, 2, 3, or 4
// If color > 4, reduce color to valid index
let mut color = order as usize;
if color > 4 {
// color = 5 --> index 1, 6 --> 2, 7 --> 3, 8 --> 4
color = color - 4;
}
colors
配列には4つの要素を持ち、かつ有効なcolor
場合は、インデックスの範囲は0〜3の条件式をチェックしているcolor
私たちはをチェックしません(インデックスが4よりも大きい場合color
、その後の関数で4に等しいインデックスへのときに我々のインデックスを車の色を割り当てる配列では、インデックス値から1を減算しますcolor - 1
。color
値4はcolors[3]
、配列と同様に処理されます。)
現在のif / else式は、8台以下の車を注文するときの実行時のパニックを防ぐためにうまく機能します。しかし、11台の車を注文すると、プログラムは9番目の注文でパニックになります。より堅牢になるように式を調整する必要があります。この改善を行うために、別のループ式を使用します。
car_factory
機能、ループ式であれば/他の条件文を交換してください。color
インデックス値が4より大きい場合に実行時のパニックを防ぐために、次の擬似コードステートメントを修正してください。// Prevent panic: Check color index, reset as needed
// If color = 1, 2, 3, or 4 - no change needed
// If color > 4, reduce to color to a valid index
let mut color = order as usize;
todo!("Replace `if/else` condition with a loop to prevent run-time panic for color > 4");
ヒント
この場合、if / else条件からループ式への変更は実際には非常に簡単です。
2. プログラムをビルドします。コードがエラーなしでコンパイルされることを確認してください。
次の出力が表示されます。
Car order 1: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("New", 0) })
Car order 2: Some(Car { color: "Green", motor: SemiAuto, roof: false, age: ("Used", 700) })
Car order 3: Some(Car { color: "Red", motor: Automatic, roof: true, age: ("Used", 1400) })
Car order 4: Some(Car { color: "Silver", motor: SemiAuto, roof: false, age: ("Used", 2100) })
Car order 5: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("New", 0) })
Car order 6: Some(Car { color: "Green", motor: Automatic, roof: true, age: ("Used", 700) })
Car order 7: Some(Car { color: "Red", motor: Manual, roof: true, age: ("Used", 1400) })
Car order 8: Some(Car { color: "Silver", motor: SemiAuto, roof: false, age: ("Used", 2100) })
Car order 9: Some(Car { color: "Blue", motor: Automatic, roof: true, age: ("New", 0) })
Car order 10: Some(Car { color: "Green", motor: SemiAuto, roof: false, age: ("Used", 700) })
Car order 11: Some(Car { color: "Red", motor: Manual, roof: true, age: ("Used", 1400) })
このモジュールでは、Rustで使用できるさまざまなループ式を調べ、ハッシュマップの操作方法を発見しました。データは、キーと値のペアとしてハッシュマップに保存されます。ハッシュマップは拡張可能です。
loop
手動でプロセスを停止するまでの式は、アクションを繰り返します。while
式をループして、条件が真である限りアクションを繰り返すことができます。このfor
式は、データ収集を反復処理するために使用されます。
この演習では、自動車プログラムを拡張して、繰り返されるアクションをループし、すべての注文を処理しました。注文を追跡するためにハッシュマップを実装しました。
このラーニングパスの次のモジュールでは、Rustコードでエラーと障害がどのように処理されるかについて詳しく説明します。
リンク: https://docs.microsoft.com/en-us/learn/modules/rust-loop-expressions/
1671687319
Among the most famous and long-lived online platforms are those for blogging. From the very beginning, people from all paths of life have found a special space to communicate with others in them. One of the best things is that in this current era, the options at your disposal are huge.
For example, you are not restricted to post only about something popular/commercial, nor to use only words.
The variety is huge, and if it is not clear to you by now, blogging as a business model is very important as well. And again, even to get paid you have so much flexibility nowadays.
Given the salience of blogging, in this article, we will talk about 6 of the most popular free blogging sites. We will mention its options to choose from, major appeals, and more.
WordPress is the biggest website builder ever created, around 40% of the web is built on it!
The magic of it is the flexibility you get; you can make your website about anything. And knowing how to code is not necessary!
It has great themes and customization tools to make your website stand out. Plus, you and your visitors will see a nice mobile version.
The free version misses the 50k plugins, advanced SEO, integrations, and others. But you can still register a new domain, connect your email, use the customization tool, etc.
Let me guide you through its theme to illustrate its variety for you. For the free version, there are 4 categories for layouts and 5 distinct features. Also, 5 subjects (e.g., art, blog, business) and 5 main styles.
You can choose from every one of these categories and in total, you got +70 templates. Every template also has several formats to choose from. Plus, there is an open live demo for anyone on the web.
There are reasons why WordPress is where it is right now and above rest a few.
Wix is one of the first ideas you get thinking of creating a website/blog. It keeps up with its competition and offers great customization, features, and accessibility. You can make a professional-looking page without knowing how to code with ease as well.
Its major appeal is that it has a bigger range of templates and it has a drag-and-drop system for customization. Plus, for those with limited time, there is an AI that makes your website fast after answering a few quick questions.
The free version has 100 templates, unlimited pages, and top-grade hosting. Plus, you can also customize your domain, add categories, hashtags, and schedule posting. Also, its presentation is great for mobiles.
The templates count with many categories. For blogging alone, there are 25 templates. With 8 subcategories: personal, food and travel, news and business, arts, fashion and beauty, sports and wellness, and podcasts.
Its editor is from a next-level kind: advance, precise, and complete. It counts with 5 tools, 9 main sections for elements addition. Plus, there is the option to check the mobile version with one click.
As its name suggests, it is only for blogs. It is completely integrated with Google services as it was bought by them in 2003. You get a free domain, flexible templates, stats, and counts with Google AdSense by default.
The interface as you can imagine is very different from those 2 above. It is more simple and not so colorful, those familiar with the open-source world will find many similarities. That is not to say it is bad or not that good, it is simply different.
As for the themes, there are 12 main categories with 49 themes in total, and customization is limited. You can change the background image, fonts, and color for each section. Plus, there is a preview that lets you check the mobile version in one click as well. As for the Layouts, there are 7 sections in which you can select and customize some gadgets.
The post creator is also simple, it counts with basic writing options. Plus, you can add links, multimedia, and special characters. The post that you’re working on is in the cloud and updates constantly. Remarkable is that you can customize the permalink of your posts.
And there is a separate section dedicated only to comments, stats, earnings, and others.
It is an advanced website creator, bought by Squarespace in 2018, that competes with Wix in the customization front.
Its free plan counts with 500Mb storage, domain customization, lead capture, and contact forms. Plus, the usual basic SEO optimization, community forums, security, and support standards.
On themes, for blogging alone there are 6 themes. Its editor is very complete with 18 individual elements. 3 of them are premium (audio player, search box, and HD video). There are tons of forms, flashes, also fonts, and theme colors.
Something remarkable is its app center with 56 free apps with different functions to choose from. They count with a rating system, so you’ll know where to focus on. Also, it is remarkable that you can add and create groups, members, and editors in the free plan.
Medium with its focus on content and +170M readers takes a different approach. It is a type of marketplace for written posts of all kinds of topics and in all styles. The number of topics and subtopics on the platform is overwhelming, so there is space for anyone.
As for customization, it is restricted. There is no theme to choose from. And what you can do is customize the logo, accent, background, layouts, fonts, and color. Its editor is simple but complete, like Blogger’s, there isn’t much one could miss from it.
Remarkably, you count with newsletters, a space for discussion engagement with your followers, as well as stats and mobile app.
Lastly, to make money you have to get in its partner program which is free and pays based on reading time.
Last but not least is Tumblr, one of the biggest names online as its +520M posts can testify. Though the site says to be all about blogging, it is mostly about all types of content about all topics and styles/formats.
Customization is also limited, there is no theme you can choose, nor can you change colors or fonts. What you can do is to post text, photos, audio, videos, links, quotes, etc. Think of Twitter.
After a very brief analysis of the page, there are a few pieces of advice I could give you. First, texts and art are not trending, though the latter gets selected often in the staff pics. Second, most of the written content is based on takes and thoughts, with a tone similar to Twitter’s). Third, unfortunately, the site is not very organized and what gets the attention is not blogging.
But, that is not to say that you could not be a traditional blogger and find your space in there. Certainly, in such a huge platform there will always be niches. Only bear in mind that Tumblr is not aimed at that type of content and that other sites do.
To conclude, allow me to mention a few words on each platform we talked about here.
WordPress is huge and has a good number of themes but lacks some customization. Wix stands out for its customization and number of themes.
Blogger is a simpler site appropriate for bloggers that value minimalism and content.
Weebly, in turn, lacks in the number of themes but makes up with higher customization and features. Which makes it compete with Wix.
Medium, is a one-of-a-kind platform, a marketplace for ideas, attractive for all writers. Tumblr offers a different space for content creators, one that looks like a social media site.
Thanks for reading this article, we hope it has been insightful and useful.
Original article source at: https://www.blog.duomly.com/
1667904060
A Django plugin for creating AJAX driven forms in Bootstrap modal.
This repository includes Dockerfile
and docker-compose.yml
files so you can easily setup and start to experiment with django-bootstrap-modal-forms
running inside of a container on your local machine. Any changes you make in bootstrap_modal_forms
, examples
and test
folders are reflected in the container (see docker-compose.yml) and the data stored in sqlite3 database are persistent even if you remove stopped container. Follow the steps below to run the app:
$ clone repository
$ cd django-bootstrap-modal-forms
$ docker compose up (use -d flag to run app in detached mode in the background)
$ visit 0.0.0.0:8000
Install django-bootstrap-modal-forms
:
$ pip install django-bootstrap-modal-forms
Add bootstrap_modal_forms
to your INSTALLED_APPS in settings.py:
INSTALLED_APPS = [
...
'bootstrap_modal_forms',
...
]
Include Bootstrap, jQuery and jquery.bootstrap.modal.forms.js
on every page where you would like to set up the AJAX driven Django forms in Bootstrap modal.
IMPORTANT: Adjust Bootstrap and jQuery file paths to match yours, but include jquery.bootstrap.modal.forms.js
exactly as in code bellow.
<head>
<link rel="stylesheet" href="{% static 'assets/css/bootstrap.css' %}">
</head>
<body>
<script src="{% static 'assets/js/bootstrap.js' %}"></script>
<script src="{% static 'assets/js/jquery.js' %}"></script>
<script src="{% static 'js/jquery.bootstrap.modal.forms.js' %}"></script>
<!-- You can alternatively load the minified version -->
<script src="{% static 'js/jquery.bootstrap.modal.forms.min.js' %}"></script>
</body>
index.html
<script type="text/javascript">
$(document).ready(function() {
$("#create-book").modalForm({
formURL: "{% url 'create_book' %}"
});
});
</script>
modalForm
opens modalformURL
is appended to the modalformURL
success_url
and shows success_message
, which are both defined in related Django viewDefine BookModelForm and inherit built-in form BSModalModelForm
.
forms.py
from .models import Book
from bootstrap_modal_forms.forms import BSModalModelForm
class BookModelForm(BSModalModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'price']
Define form's html and save it as Django template.
formURL
defined in #6.class="invalid"
or custom errorClass
(see paragraph Options) to the elements that wrap the fields.class="invalid"
acts as a flag for the fields having errors after the form has been POSTed.book/create_book.html
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h5 class="modal-title">Create new Book</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{% for field in form %}
<div class="form-group{% if field.errors %} invalid{% endif %}">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }}
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
{% endfor %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create</button>
</div>
</form>
Define a class-based view BookCreateView and inherit from built-in generic view BSModalCreateView
. BookCreateView processes the form defined in #1, uses the template defined in #2 and redirects to success_url
showing success_message
.
views.py
from django.urls import reverse_lazy
from .forms import BookModelForm
from .models import Book
from bootstrap_modal_forms.generic import BSModalCreateView
class BookCreateView(BSModalCreateView):
template_name = 'examples/create_book.html'
form_class = BookModelForm
success_message = 'Success: Book was created.'
success_url = reverse_lazy('index')
Define URL for the view in #3.
from django.urls import path
from books import views
urlpatterns = [
path('', views.Index.as_view(), name='index'),
path('create/', views.BookCreateView.as_view(), name='create_book'),
]
Define the Bootstrap modal window and html element triggering modal opening.
modalForms
in single template (see #6).id
and the same value should also be set as modalID
option when instantiating modalForm
on trigger element.id="create-book"
) is used for instantiation of modalForm
in #6.modalForm
is bound to it.<div class="modal-content"></div>
and sets action attribute of the form to formURL
set in #6.index.html
<div class="modal fade" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog" role="document">
<div class="modal-content"></div>
</div>
</div>
<!-- Create book button -->
<button id="create-book" class="btn btn-primary" type="button" name="button">Create book</button>
Add script to the template from #5 and bind the modalForm
to the trigger element. Set BookCreateView URL defined in #4 as formURL
property of modalForm
.
modalForm
with unique URL to it.modalID
, modalContent
, modalForm
and errorClass
are used in this example, while formURL
is customized. If you customize any other option adjust the code of the above examples accordingly.index.html
<script type="text/javascript">
$(document).ready(function() {
$("#create-book").modalForm({
formURL: "{% url 'create_book' %}"
});
});
</script>
Set asyncUpdate and asyncSettings settings to create or update objects without page redirection to successUrl and define whether a modal should close or stay opened after form submission. See comments in example below and paragraph modalForm options for explanation of asyncSettings. See examples on how to properly reinstantiate modal forms for all CRUD buttons when using async options.
index.html
<!-- asyncSettings.dataElementId -->
<table id="books-table" class="table">
<thead>
...
</thead>
<tbody>
{% for book in books %}
<tr>
...
<!-- Update book buttons -->
<button type="button" class="update-book btn btn-sm btn-primary" data-form-url="{% url 'update_book' book.pk %}">
<span class="fa fa-pencil"></span>
</button>
...
</td>
</tr>
{% endfor %}
</tbody>
</table>
<script type="text/javascript">
$(function () {
...
# asyncSettings.successMessage
var asyncSuccessMessage = [
"<div ",
"style='position:fixed;top:0;z-index:10000;width:100%;border-radius:0;' ",
"class='alert alert-icon alert-success alert-dismissible fade show mb-0' role='alert'>",
"Success: Book was updated.",
"<button type='button' class='close' data-dismiss='alert' aria-label='Close'>",
"<span aria-hidden='true'>×</span>",
"</button>",
"</div>",
"<script>",
"$('.alert').fadeTo(2000, 500).slideUp(500, function () {$('.alert').slideUp(500).remove();});",
"<\/script>"
].join();
# asyncSettings.addModalFormFunction
function updateBookModalForm() {
$(".update-book").each(function () {
$(this).modalForm({
formURL: $(this).data("form-url"),
asyncUpdate: true,
asyncSettings: {
closeOnSubmit: false,
successMessage: asyncSuccessMessage
dataUrl: "books/",
dataElementId: "#books-table",
dataKey: "table",
addModalFormFunction: updateBookModalForm
}
});
});
}
updateBookModalForm();
...
});
</script>
urls.py
from django.urls import path
from . import views
urlpatterns = [
...
# asyncSettings.dataUrl
path('books/', views.books, name='books'),
...
]
views.py
from django.http import JsonResponse
from django.template.loader import render_to_string
from .models import Book
def books(request):
data = dict()
if request.method == 'GET':
books = Book.objects.all()
# asyncSettings.dataKey = 'table'
data['table'] = render_to_string(
'_books_table.html',
{'books': books},
request=request
)
return JsonResponse(data)
modalID
Sets the custom id of the modal. Default: "#modal"
modalContent
Sets the custom class of the element to which the form's html is appended. If you change modalContent
to the custom class, you should also change modalForm
accordingly. To keep Bootstrap's modal style you should than copy Bootstrap's style for modal-content
and set it to your new modalContent class. Default: ".modal-content"
modalForm
Sets the custom form selector. Default: ".modal-content form"
formURL
Sets the url of the form's view and html. Default: null
isDeleteForm
Defines if form is used for deletion. Should be set to true
for deletion forms. Default: false
errorClass
Sets the custom class for the form fields having errors. Default: ".invalid"
asyncUpdate
Sets asynchronous content update after form submission. Default: false
asyncSettings.closeOnSubmit
Sets whether modal closes or not after form submission. Default: false
asyncSettings.successMessage
Sets successMessage shown after succesful for submission. Should be set to string defining message element. See asyncSuccessMessage
example above. Default: null
asyncSettings.dataUrl
Sets url of the view returning new queryset = all of the objects plus newly created or updated one after asynchronous update. Default: null
asyncSettings.dataElementId
Sets the id
of the element which rerenders asynchronously updated queryset. Default: null
asyncSettings.dataKey
Sets the key containing asynchronously updated queryset in the data dictionary returned from the view providing updated queryset. Default: null
asyncSettings.addModalFormFunction
Sets the method needed for reinstantiation of event listeners on buttons (single or all CRUD buttons) after asynchronous update. Default: null
triggerElement.modalForm({
modalID: "#modal",
modalContent: ".modal-content",
modalForm: ".modal-content form",
formURL: null,
isDeleteForm: false,
errorClass: ".invalid",
asyncUpdate: false,
asyncSettings: {
closeOnSubmit: false,
successMessage: null,
dataUrl: null,
dataElementId: null,
dataKey: null,
addModalFormFunction: null
}
});
Import forms with from bootstrap_modal_forms.forms import BSModalForm
.
BSModalForm
Inherits PopRequestMixin and Django's forms.Form.
BSModalModelForm
Inherits PopRequestMixin, CreateUpdateAjaxMixin and Django's forms.ModelForm.
Import mixins with from bootstrap_modal_forms.mixins import PassRequestMixin
.
PassRequestMixin
Puts the request into the form's kwargs.
PopRequestMixin
Pops request out of the kwargs and attaches it to the form's instance.
CreateUpdateAjaxMixin
Saves or doesn't save the object based on the request type.
DeleteMessageMixin
Deletes object if request is not ajax request.
LoginAjaxMixin
Authenticates user if request is not ajax request.
Import generic views with from bootstrap_modal_forms.generic import BSModalFormView
.
BSModalFormView
Inherits PassRequestMixin and Django's generic.FormView.
BSModalCreateView
Inherits PassRequestMixin and Django's SuccessMessageMixin and generic.CreateView.
BSModalUpdateView
Inherits PassRequestMixin and Django's SuccessMessageMixin and generic.UpdateView.
BSModalReadView
Inherits Django's generic.DetailView.
BSModalDeleteView
Inherits DeleteMessageMixin and Django's generic.DeleteView.
To see django-bootstrap-modal-forms
in action clone the repository and run the examples locally:
$ git clone https://github.com/trco/django-bootstrap-modal-forms.git
$ cd django-bootstrap-modal-forms
$ pip install -r requirements.txt
$ python manage.py migrate
$ python manage.py runserver
Run unit and functional tests inside of project folder:
$ python manage.py test
For explanation how all the parts of the code work together see paragraph Usage. To test the working solution presented here clone and run Examples.
forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from bootstrap_modal_forms.mixins import PopRequestMixin, CreateUpdateAjaxMixin
class CustomUserCreationForm(PopRequestMixin, CreateUpdateAjaxMixin,
UserCreationForm):
class Meta:
model = User
fields = ['username', 'password1', 'password2']
signup.html
{% load widget_tweaks %}
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Sign up</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Sign up</button>
</div>
</form>
views.py
from django.urls import reverse_lazy
from bootstrap_modal_forms.generic import BSModalCreateView
from .forms import CustomUserCreationForm
class SignUpView(BSModalCreateView):
form_class = CustomUserCreationForm
template_name = 'examples/signup.html'
success_message = 'Success: Sign up succeeded. You can now Log in.'
success_url = reverse_lazy('index')
urls.py
from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
path('signup/', views.SignUpView.as_view(), name='signup')
]
.html file containing modal, trigger element and script instantiating modalForm
<div class="modal fade" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog" role="document">
<div class="modal-content"></div>
</div>
</div>
<button id="signup-btn" class="btn btn-primary" type="button" name="button">Sign up</button>
<script type="text/javascript">
$(function () {
// Sign up button
$("#signup-btn").modalForm({
formURL: "{% url 'signup' %}"
});
});
</script>
For explanation how all the parts of the code work together see paragraph Usage. To test the working solution presented here clone and run Examples.
You can set the login redirection by setting the LOGIN_REDIRECT_URL
in settings.py
.
You can also set the custom login redirection by:
success_url
to the extra_context
of CustomLoginView
success_url
variable as a value of the hidden input field
with name="next"
within the Login form htmlforms.py
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User
class CustomAuthenticationForm(AuthenticationForm):
class Meta:
model = User
fields = ['username', 'password']
login.html
{% load widget_tweaks %}
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Log in</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
<!-- Hidden input field for custom redirection after successful login -->
<input type="hidden" name="next" value="{{ success_url }}">
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Log in</button>
</div>
</form>
views.py
from django.urls import reverse_lazy
from bootstrap_modal_forms.generic import BSModalLoginView
from .forms import CustomAuthenticationForm
class CustomLoginView(BSModalLoginView):
authentication_form = CustomAuthenticationForm
template_name = 'examples/login.html'
success_message = 'Success: You were successfully logged in.'
extra_context = dict(success_url=reverse_lazy('index'))
urls.py
from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
path('login/', views.CustomLoginView.as_view(), name='login')
]
.html file containing modal, trigger element and script instantiating modalForm
<div class="modal fade" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog" role="document">
<div class="modal-content"></div>
</div>
</div>
<button id="login-btn" class="btn btn-primary" type="button" name="button">Sign up</button>
<script type="text/javascript">
$(function () {
// Log in button
$("#login-btn").modalForm({
formURL: "{% url 'login' %}"
});
});
</script>
For explanation how all the parts of the code work together see paragraph Usage. To test the working solution presented here clone and run Examples.
forms.py
from .models import Book
from bootstrap_modal_forms.forms import BSModalModelForm
class BookModelForm(BSModalModelForm):
class Meta:
model = Book
exclude = ['timestamp']
create_book.html
{% load widget_tweaks %}
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Create Book</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Create</button>
</div>
</form>
update_book.html
{% load widget_tweaks %}
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Update Book</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Update</button>
</div>
</form>
read_book.html
{% load widget_tweaks %}
<div class="modal-header">
<h3 class="modal-title">Book details</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="">
Title: {{ book.title }}
</div>
<div class="">
Author: {{ book.author }}
</div>
<div class="">
Price: {{ book.price }} €
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
{% load widget_tweaks %}
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Delete Book</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete book with title
<strong>{{ book.title }}</strong>?</p>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-danger">Delete</button>
</div>
</form>
views.py
from django.urls import reverse_lazy
from django.views import generic
from .forms import BookModelForm
from .models import Book
from bootstrap_modal_forms.generic import (
BSModalCreateView,
BSModalUpdateView,
BSModalReadView,
BSModalDeleteView
)
class Index(generic.ListView):
model = Book
context_object_name = 'books'
template_name = 'index.html'
# Create
class BookCreateView(BSModalCreateView):
template_name = 'examples/create_book.html'
form_class = BookModelForm
success_message = 'Success: Book was created.'
success_url = reverse_lazy('index')
# Update
class BookUpdateView(BSModalUpdateView):
model = Book
template_name = 'examples/update_book.html'
form_class = BookModelForm
success_message = 'Success: Book was updated.'
success_url = reverse_lazy('index')
# Read
class BookReadView(BSModalReadView):
model = Book
template_name = 'examples/read_book.html'
# Delete
class BookDeleteView(BSModalDeleteView):
model = Book
template_name = 'examples/delete_book.html'
success_message = 'Success: Book was deleted.'
success_url = reverse_lazy('index')
urls.py
from django.urls import path
from books import views
urlpatterns = [
path('', views.Index.as_view(), name='index'),
path('create/', views.BookCreateView.as_view(), name='create_book'),
path('update/<int:pk>', views.BookUpdateView.as_view(), name='update_book'),
path('read/<int:pk>', views.BookReadView.as_view(), name='read_book'),
path('delete/<int:pk>', views.BookDeleteView.as_view(), name='delete_book')
]
.html file containing modal, trigger elements and script instantiating modalForms
<!-- Modal 1 with id="create-book"-->
<div class="modal fade" id="create-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
<!-- Modal 2 with id="modal" -->
<div class="modal fade" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog" role="document">
<div class="modal-content"></div>
</div>
</div>
<!-- Create book button -->
<button id="create-book" class="btn btn-primary" type="button" name="button">Create book</button>
{% for book in books %}
<div class="text-center">
<!-- Read book buttons -->
<button type="button" class="read-book bs-modal btn btn-sm btn-primary" data-form-url="{% url 'read_book' book.pk %}">
<span class="fa fa-eye"></span>
</button>
<!-- Update book buttons -->
<button type="button" class="update-book bs-modal btn btn-sm btn-primary" data-form-url="{% url 'update_book' book.pk %}">
<span class="fa fa-pencil"></span>
</button>
<!-- Delete book buttons -->
<button type="button" class="delete-book bs-modal btn btn-sm btn-danger" data-form-url="{% url 'delete_book' book.pk %}">
<span class="fa fa-trash"></span>
</button>
</div>
{% endfor %}
<script type="text/javascript">
$(function () {
// Read book buttons
$(".read-book").each(function () {
$(this).modalForm({formURL: $(this).data("form-url")});
});
// Delete book buttons - formURL is retrieved from the data of the element
$(".delete-book").each(function () {
$(this).modalForm({formURL: $(this).data("form-url"), isDeleteForm: true});
});
// Create book button opens form in modal with id="create-modal"
$("#create-book").modalForm({
formURL: "{% url 'create_book' %}",
modalID: "#create-modal"
});
});
</script>
data-form-url
attribute of each Update, Read and Delete button should be set to relevant URL with pk argument of the object to be updated, read or deleted.data-form-url
URLs should than be set as formURLs
for modalForms
bound to the buttons.For explanation how all the parts of the code work together see paragraph Usage. To test the working solution presented here clone and run Examples.
forms.py
from bootstrap_modal_forms.forms import BSModalForm
class BookFilterForm(BSModalForm):
type = forms.ChoiceField(choices=Book.BOOK_TYPES)
class Meta:
fields = ['type']
filter_book.html
{% load widget_tweaks %}
<form method="post" action="">
{% csrf_token %}
<div class="modal-header">
<h3 class="modal-title">Filter Books</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="{% if form.non_field_errors %}invalid{% endif %} mb-2">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" placeholder=field.label %}
<div class="{% if field.errors %} invalid{% endif %}">
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Filter</button>
</div>
</form>
views.py
class BookFilterView(BSModalFormView):
template_name = 'examples/filter_book.html'
form_class = BookFilterForm
def form_valid(self, form):
self.filter = '?type=' + form.cleaned_data['type']
response = super().form_valid(form)
return response
def get_success_url(self):
return reverse_lazy('index') + self.filter
urls.py
from django.urls import path
from . import views
app_name = 'accounts'
urlpatterns = [
path('filter/', views.BookFilterView.as_view(), name='filter_book'),
]
index.html
...
<button id="filter-book" class="filter-book btn btn-primary" type="button" name="button" data-form-url="{% url 'filter_book' %}">
<span class="fa fa-filter mr-2"></span>Filter books
</button>
...
<script type="text/javascript">
$(function () {
...
$("#filter-book").each(function () {
$(this).modalForm({formURL: $(this).data('form-url')});
});
...
});
</script>
This is an Open Source project and any contribution is appreciated.
Author: trco
Source Code: https://github.com/trco/django-bootstrap-modal-forms
License: MIT license
1647540000
The Substrate Knowledge Map provides information that you—as a Substrate hackathon participant—need to know to develop a non-trivial application for your hackathon submission.
The map covers 6 main sections:
Each section contains basic information on each topic, with links to additional documentation for you to dig deeper. Within each section, you'll find a mix of quizzes and labs to test your knowledge as your progress through the map. The goal of the labs and quizzes is to help you consolidate what you've learned and put it to practice with some hands-on activities.
One question we often get is why learn the Substrate framework when we can write smart contracts to build decentralized applications?
The short answer is that using the Substrate framework and writing smart contracts are two different approaches.
Traditional smart contract platforms allow users to publish additional logic on top of some core blockchain logic. Since smart contract logic can be published by anyone, including malicious actors and inexperienced developers, there are a number of intentional safeguards and restrictions built around these public smart contract platforms. For example:
Fees: Smart contract developers must ensure that contract users are charged for the computation and storage they impose on the computers running their contract. With fees, block creators are protected from abuse of the network.
Sandboxed: A contract is not able to modify core blockchain storage or storage items of other contracts directly. Its power is limited to only modifying its own state, and the ability to make outside calls to other contracts or runtime functions.
Reversion: Contracts can be prone to undesirable situations that lead to logical errors when wanting to revert or upgrade them. Developers need to learn additional patterns such as splitting their contract's logic and data to ensure seamless upgrades.
These safeguards and restrictions make running smart contracts slower and more costly. However, it's important to consider the different developer audiences for contract development versus Substrate runtime development.
Building decentralized applications with smart contracts allows your community to extend and develop on top of your runtime logic without worrying about proposals, runtime upgrades, and so on. You can also use smart contracts as a testing ground for future runtime changes, but done in an isolated way that protects your network from any errors the changes might introduce.
In summary, smart contract development:
Unlike traditional smart contract development, Substrate runtime development offers none of the network protections or safeguards. Instead, as a runtime developer, you have total control over how the blockchain behaves. However, this level of control also means that there is a higher barrier to entry.
Substrate is a framework for building blockchains, which almost makes comparing it to smart contract development like comparing apples and oranges. With the Substrate framework, developers can build smart contracts but that is only a fraction of using Substrate to its full potential.
With Substrate, you have full control over the underlying logic that your network's nodes will run. You also have full access for modifying and controlling each and every storage item across your runtime modules. As you progress through this map, you'll discover concepts and techniques that will help you to unlock the potential of the Substrate framework, giving you the freedom to build the blockchain that best suits the needs of your application.
You'll also discover how you can upgrade the Substrate runtime with a single transaction instead of having to organize a community hard-fork. Upgradeability is one of the primary design features of the Substrate framework.
In summary, runtime development:
To learn more about using smart contracts within Substrate, refer to the Smart Contract - Overview page as well as the Polkadot Builders Guide.
If you need any community support, please join the following channels based on the area where you need help:
Alternatively, also look for support on Stackoverflow where questions are tagged with "substrate" or on the Parity Subport repo.
Use the following links to explore the sites and resources available on each:
Substrate Developer Hub has the most comprehensive all-round coverage about Substrate, from a "big picture" explanation of architecture to specific technical concepts. The site also provides tutorials to guide you as your learn the Substrate framework and the API reference documentation. You should check this site first if you want to look up information about Substrate runtime development. The site consists of:
Knowledge Base: Explaining the foundational concepts of building blockchain runtimes using Substrate.
Tutorials: Hand-on tutorials for developers to follow. The first SIX tutorials show the fundamentals in Substrate and are recommended for every Substrate learner to go through.
How-to Guides: These resources are like the O'Reilly cookbook series written in a task-oriented way for readers to get the job done. Some examples of the topics overed include:
API docs: Substrate API reference documentation.
Substrate Node Template provides a light weight, minimal Substrate blockchain node that you can set up as a local development environment.
Substrate Front-end template provides a front-end interface built with React using Polkadot-JS API to connect to any Substrate node. Developers are encouraged to start new Substrate projects based on these templates.
If you face any technical difficulties and need support, feel free to join the Substrate Technical matrix channel and ask your questions there.
Polkadot Wiki documents the specific behavior and mechanisms of the Polkadot network. The Polkadot network allows multiple blockchains to connect and pass messages to each other. On the wiki, you can learn about how Polkadot—built using Substrate—is customized to support inter-blockchain message passing.
Polkadot JS API doc: documents how to use the Polkadot-JS API. This JavaScript-based API allows developers to build custom front-ends for their blockchains and applications. Polkadot JS API provides a way to connect to Substrate-based blockchains to query runtime metadata and send transactions.
👉 Submit your answers to Quiz #1
Here you will set up your local machine to install the Rust compiler—ensuring that you have both stable and nightly versions installed. Both stable and nightly versions are required because currently a Substrate runtime is compiled to a native binary using the stable Rust compiler, then compiled to a WebAssembly (WASM) binary, which only the nightly Rust compiler can do.
Also refer to:
👉 Complete Lab #1: Run a Substrate node
Polkadot JS Apps is the canonical front-end to interact with any Substrate-based chain.
You can configure whichever endpoint you want it to connected to, even to your localhost
running node. Refer to the following two diagrams.
👉 Complete Quiz #2
👉 Complete Lab #2: Using Polkadot-JS Apps
Notes: If you are connecting Apps to a custom chain (or your locally-running node), you may need to specify your chain's custom data types in JSON under Settings > Developer.
Polkadot-JS Apps only receives a series of bytes from the blockchain. It is up to the developer to tell it how to decode and interpret these custom data type. To learn more on this, refer to:
You will also need to create an account. To do so, follow these steps on account generation. You'll learn that you can also use the Polkadot-JS Browser Plugin (a Metamask-like browser extension to manage your Substrate accounts) and it will automatically be imported into Polkadot-JS Apps.
Notes: When you run a Substrate chain in development mode (with the
--dev
flag), well-known accounts (Alice
,Bob
,Charlie
, etc.) are always created for you.
👉 Complete Lab #3: Create an Account
You need to know some Rust programming concepts and have a good understanding on how blockchain technology works in order to make the most of developing with Substrate. The following resources will help you brush up in these areas.
You will need familiarize yourself with Rust to understand how Substrate is built and how to make the most of its capabilities.
If you are new to Rust, or need a brush up on your Rust knowledge, please refer to The Rust Book. You could still continue learning about Substrate without knowing Rust, but we recommend you come back to this section whenever in doubt about what any of the Rust syntax you're looking at means. Here are the parts of the Rust book we recommend you familiarize yourself with:
Given that you'll be writing a blockchain runtime, you need to know what a blockchain is, and how it works. The **Web3 Blockchain Fundamental MOOC Youtube video series provides a good basis for understanding key blockchain concepts and how blockchains work.
The lectures we recommend you watch are: lectures 1 - 7 and lecture 10. That's 8 lectures, or about 4 hours of video.
👉 Complete Quiz #3
To know more about the high level architecture of Substrate, please go through the Knowledge Base articles on Getting Started: Overview and Getting Started: Architecture.
In this document, we assume you will develop a Substrate runtime with FRAME (v2). This is what a Substrate node consists of.
Each node has many components that manage things like the transaction queue, communicating over a P2P network, reaching consensus on the state of the blockchain, and the chain's actual runtime logic (aka the blockchain runtime). Each aspect of the node is interesting in its own right, and the runtime is particularly interesting because it contains the business logic (aka "state transition function") that codifies the chain's functionality. The runtime contains a collection of pallets that are configured to work together.
On the node level, Substrate leverages libp2p for the p2p networking layer and puts the transaction pool, consensus mechanism, and underlying data storage (a key-value database) on the node level. These components all work "under the hood", and in this knowledge map we won't cover them in detail except for mentioning their existence.
👉 Complete Quiz #4
In our Developer Hub, we have a thorough coverage on various subjects you need to know to develop with Substrate. So here we just list out the key topics and reference back to Developer Hub. Please go through the following key concepts and the directed resources to know the fundamentals of runtime development.
Key Concept: Runtime, this is where the blockchain state transition function (the blockchain application-specific logic) is defined. It is about composing multiple pallets (can be understood as Rust modules) together in the runtime and hooking them up together.
Runtime Development: Execution, this article describes how a block is produced, and how transactions are selected and executed to reach the next "stage" in the blockchain.
Runtime Develpment: Pallets, this article describes what the basic structure of a Substrate pallet is consists of.
Runtime Development: FRAME, this article gives a high level overview of the system pallets Substrate already implements to help you quickly develop as a runtime engineer. Have a quick skim so you have a basic idea of the different pallets Substrate is made of.
👉 Complete Lab #4: Adding a Pallet into a Runtime
Runtime Development: Storage, this article describes how data is stored on-chain and how you could access them.
Runtime Development: Events & Errors, this page describe how external parties know what has happened in the blockchain, via the emitted events and errors when executing transactions.
Notes: All of the above concepts we leverage on the
#[pallet::*]
macro to define them in the code. If you are interested to learn more about what other types of pallet macros exist go to the FRAME macro API documentation and this doc on some frequently used Substrate macros.
👉 Complete Lab #5: Building a Proof-of-Existence dApp
👉 Complete Lab #6: Building a Substrate Kitties dApp
👉 Complete Quiz #5
Polkadot JS API is the javascript API for Substrate. By using it you can build a javascript front end or utility and interact with any Substrate-based blockchain.
The Substrate Front-end Template is an example of using Polkadot JS API in a React front-end.
👉 Complete Lab #7: Using Polkadot-JS API
👉 Complete Quiz #6: Using Polkadot-JS API
Learn about the difference between smart contract development vs Substrate runtime development, and when to use each here.
In Substrate, you can program smart contracts using ink!.
👉 Complete Quiz #7: Using ink!
A lot 😄
On-chain runtime upgrades. We have a tutorial on On-chain (forkless) Runtime Upgrade. This tutorial introduces how to perform and schedule a runtime upgrade as an on-chain transaction.
About transaction weight and fee, and benchmarking your runtime to determine the proper transaction cost.
There are certain limits to on-chain logic. For instance, computation cannot be too intensive that it affects the block output time, and computation must be deterministic. This means that computation that relies on external data fetching cannot be done on-chain. In Substrate, developers can run these types of computation off-chain and have the result sent back on-chain via extrinsics.
Tightly- and Loosely-coupled pallets, calling one pallet's functions from another pallet via trait specification.
Blockchain Consensus Mechansim, and a guide on customizing it to proof-of-work here.
Parachains: one key feature of Substrate is the capability of becoming a parachain for relay chains like Polkadot. You can develop your own application-specific logic in your chain and rely on the validator community of the relay chain to secure your network, instead of building another validator community yourself. Learn more with the following resources:
Author: substrate-developer-hub
Source Code: https://github.com/substrate-developer-hub/hackathon-knowledge-map
License:
1607523900
In this video, We have created a Tab design in HTML and CSS without using JavaScript. I have also provided HTML and CSS code on my website, you can visit my website by clicking given link.
Subscribe: https://www.youtube.com/@CodingLabYT/featured
Source Code :
HTML :
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<!--<title> CSS Vertical Tabs </title>-->
<link rel="stylesheet" href="style.css">
<!-- Fontawesome CDN Link -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="container">
<div class="topic">CSS Vertical Tabs.</div>
<div class="content">
<input type="radio" name="slider" checked id="home">
<input type="radio" name="slider" id="blog">
<input type="radio" name="slider" id="help">
<input type="radio" name="slider" id="code">
<input type="radio" name="slider" id="about">
<div class="list">
<label for="home" class="home">
<i class="fas fa-home"></i>
<span class="title">Home</span>
</label>
<label for="blog" class="blog">
<span class="icon"><i class="fas fa-blog"></i></span>
<span class="title">Blog</span>
</label>
<label for="help" class="help">
<span class="icon"><i class="far fa-envelope"></i></span>
<span class="title">Help</span>
</label>
<label for="code" class="code">
<span class="icon"><i class="fas fa-code"></i></span>
<span class="title">Code</span>
</label>
<label for="about" class="about">
<span class="icon"><i class="far fa-user"></i></span>
<span class="title">About</span>
</label>
<div class="slider"></div>
</div>
<div class="text-content">
<div class="home text">
<div class="title">Home Content</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quasi excepturi ducimus sequi dignissimos expedita tempore omnis quos cum, possimus, aspernatur esse nihil commodi est maiores dolorum rem iusto atque, beatae voluptas sit eligendi architecto dolorem temporibus. Non magnam ipsam, voluptas quasi nam dicta ut. Ad corrupti aliquid obcaecati alias, nemo veritatis porro nisi eius sequi dignissimos ea repellendus quibusdam minima ipsum animi quae, libero quisquam a! Laudantium iste est sapiente, ullam itaque odio iure laborum voluptatem quaerat tempore doloremque quam modi, atque minima enim saepe! Dolorem rerum minima incidunt, officia!</p>
</div>
<div class="blog text">
<div class="title">Blog Content</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias tempora, unde reprehenderit incidunt excepturi blanditiis ullam dignissimos provident quam? Fugit, enim! Architecto ad officiis dignissimos ex quae iusto amet pariatur, ea eius aut velit, tempora magnam hic autem maiores unde corrupti tenetur delectus! Voluptatum praesentium labore consectetur ea qui illum illo distinctio, sunt, ipsam rerum optio quibusdam cum a? Aut facilis non fuga molestiae voluptatem omnis reprehenderit, dignissimos commodi repellat sapiente natus ipsam, ipsa distinctio. Ducimus repudiandae fuga aliquid, numquam.</p>
</div>
<div class="help text">
<div class="title">Help Content</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maiores error neque, officia excepturi dolores quis dolor, architecto iusto deleniti a soluta nostrum. Fuga reiciendis beatae, dicta voluptatem, vitae eligendi maxime accusamus. Amet totam aut odio velit cumque autem neque sequi provident mollitia, nisi sunt maiores facilis debitis in officiis asperiores saepe quo soluta laudantium ad non quisquam! Repellendus culpa necessitatibus aliquam quod mollitia perspiciatis ducimus doloribus perferendis autem, omnis, impedit, veniam qui dolorem? Ipsam nihil assumenda, sit ratione blanditiis eius aliquam libero iusto, dolorum aut perferendis modi laboriosam sint dolor.</p>
</div>
<div class="code text">
<div class="title">Code Content</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore magnam vitae inventore blanditiis nam tenetur voluptates doloribus error atque reprehenderit, necessitatibus minima incidunt a eius corrupti placeat, quasi similique deserunt, harum? Quia ut impedit ab earum expedita soluta repellat perferendis hic tempora inventore, accusantium porro consequuntur quisquam et assumenda distinctio dignissimos doloremque enim nemo delectus deserunt! Ullam perspiciatis quae aliquid animi quam amet deleniti, at dolorum tenetur, tempore laborum.</p>
</div>
<div class="about text">
<div class="title">About Content</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Necessitatibus incidunt possimus quas ad, sit nam veniam illo ullam sapiente, aspernatur fugiat atque. Laboriosam libero voluptatum molestiae veniam earum quisquam, laudantium aperiam, eligendi dicta animi maxime sunt non nisi, ex, ipsa! Soluta ex, quibusdam voluptatem distinctio asperiores recusandae veritatis optio dolorem illo nesciunt quos ullam, dicta numquam ipsam cumque sed. Blanditiis omnis placeat, enim sit dicta eligendi voluptatibus laborum consectetur repudiandae tempora numquam molestiae rerum mollitia nemo. Velit perspiciatis, nesciunt, quo illo quas error debitis molestiae et sapiente neque tempore natus?</p>
</div>
</div>
</div>
</div>
</body>
</html>
CSS :
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body{
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #dad3f8;
}
::selection{
background: #6d50e2;
color: #fff;
}
.container{
max-width: 950px;
width: 100%;
padding: 40px 50px 40px 40px;
background: #fff;
margin: 0 20px;
border-radius: 12px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
}
.container .topic{
font-size: 30px;
font-weight: 500;
margin-bottom: 20px;
}
.content{
display: flex;
align-items: center;
justify-content: space-between;
}
.content .list{
display: flex;
flex-direction: column;
width: 20%;
margin-right: 50px;
position: relative;
}
.content .list label{
height: 60px;
font-size: 22px;
font-weight: 500;
line-height: 60px;
cursor: pointer;
padding-left: 25px;
transition: all 0.5s ease;
color: #333;
z-index: 12;
}
#home:checked ~ .list label.home,
#blog:checked ~ .list label.blog,
#help:checked ~ .list label.help,
#code:checked ~ .list label.code,
#about:checked ~ .list label.about{
color: #fff;
}
.content .list label:hover{
color: #6d50e2;
}
.content .slider{
position: absolute;
left: 0;
top: 0;
height: 60px;
width: 100%;
border-radius: 12px;
background: #6d50e2;
transition: all 0.4s ease;
}
#home:checked ~ .list .slider{
top: 0;
}
#blog:checked ~ .list .slider{
top: 60px;
}
#help:checked ~ .list .slider{
top: 120px;
}
#code:checked ~ .list .slider{
top: 180px;
}
#about:checked ~ .list .slider{
top: 240px;
}
.content .text-content{
width: 80%;
height: 100%;
}
.content .text{
display: none;
}
.content .text .title{
font-size: 25px;
margin-bottom: 10px;
font-weight: 500;
}
.content .text p{
text-align: justify;
}
.content .text-content .home{
display: block;
}
#home:checked ~ .text-content .home,
#blog:checked ~ .text-content .blog,
#help:checked ~ .text-content .help,
#code:checked ~ .text-content .code,
#about:checked ~ .text-content .about{
display: block;
}
#blog:checked ~ .text-content .home,
#help:checked ~ .text-content .home,
#code:checked ~ .text-content .home,
#about:checked ~ .text-content .home{
display: none;
}
.content input{
display: none;
}
#javascript #html #css