PAN.JS (หรือ P.JS ) เป็นแสง (<40KO) และ กรอบ JS แบบง่าย ๆ ที่ทำขึ้นเพื่อช่วยให้คุณพัฒนาเว็บแอปพลิเคชันที่มีโครงสร้างดีอย่างรวดเร็ว
คุณสามารถจัดระเบียบเว็บแอปพลิเคชันของคุณเป็น ส่วนประกอบ และ เครื่องมือ มันมาพร้อมกับสิ่งที่มีประโยชน์บางอย่าง เพียงรวมไฟล์ JS ใน HTML ของคุณและเริ่มใช้มัน P.JS ยังอยู่ในระหว่างการพัฒนาอย่าลังเลถ้าคุณมีคำแนะนำใด ๆ
สารบัญ
P.JS ไม่มีการพึ่งพา (ไม่คุณไม่จำเป็นต้องใช้ jQuery) เข้ากันได้กับเบราว์เซอร์ที่ทันสมัยทั้งหมดลงไปที่ IE8
ขึ้นอยู่กับเบราว์เซอร์และคลาสที่คุณใช้คุณอาจต้องใช้โพลีฟิลล์ซึ่งรวมอยู่ในโฟลเดอร์ SRC/Polyfills
บิลด์เริ่มต้นมีโพลีฟิลล์ที่จำเป็นทั้งหมด แต่คุณสามารถใช้เวอร์ชัน no-compatibility
มีสองวิธีในการใช้ P.JS
คุณสามารถใช้เป็นไลบรารีที่เรียบง่ายโดยการสร้างอินสแตนซ์เครื่องมือหรือคุณสามารถใช้เป็นเฟรมเวิร์กได้โดยขยาย P.JS เพื่อสร้างเครื่องมือและส่วนประกอบของคุณเอง
< script src =" ../../builds/pan-0.3.min.js " > </ script > var viewport = new P . Tools . Viewport ( ) ;
viewport . on ( 'resize' , function ( width , height )
{
console . log ( width , height ) ;
} ) ; สร้างเครื่องมือและส่วนประกอบของคุณเองตามคลาส P.JS คุณสามารถใส่ส่วนประกอบของคุณไว้ในวัตถุ P.Components หรือคุณสามารถสร้างเนมสเปซของคุณเองเช่น Foo.Bar.My_Class
มรดกขึ้นอยู่กับรหัส Resig John ที่มีการปรับปรุงบางอย่างเช่น Deep Property Merging, Singleton, Defualt Options ฯลฯ
P.JS ได้รับการพัฒนาในโหมดที่เข้มงวด ทำตามที่คุณทำและอย่าลังเลที่จะแบ่งปันเครื่องมือและส่วนประกอบที่กำหนดเองของคุณ
< script src =" ../../builds/pan-0.3.min.js " > </ script > // Create a class wrapping the all application
P . Components . My_App = P . Core . Abstract . extend (
{
construct : function ( )
{
// Instantiate a sidebar and header
this . sidebar = new P . Components . My_Sidebar ( { color : 'blue' } ) ;
this . header = new P . Components . My_Header ( ) ;
}
} ) ;
// Create a class for the sidebar
P . Components . My_Sidebar = P . Core . Abstract . extend (
{
// Default options
options :
{
colors : 'red'
} ,
construct : function ( options )
{
this . _super ( options ) ;
this . main = document . querySelector ( 'aside' ) ;
console . log ( 'Init Sidebar' ) ;
}
} ) ;
// Create a class for the header
P . Components . My_Header = P . Core . Abstract . extend (
{
construct : function ( )
{
this . main = document . querySelector ( 'header' ) ;
console . log ( 'Init Header' ) ;
}
} ) ; // Let's rock
var my_app = new P . Components . My_App ( ) ; คลาสหลักคือรากฐานของ P.JS
เครื่องมือหรือส่วนประกอบทุกชิ้นที่สืบทอดมาจากหนึ่งในคลาสเหล่านั้นและคลาสที่กำหนดเองของคุณก็ควรทำเช่นกัน
P.Core.Abstract เป็นคลาสเริ่มต้น
construct จะถูกเรียกเมื่ออินสแตนซ์static ที่ตั้งค่าคลาสเป็นซิงเกิล นั่นหมายความว่าการเริ่มต้นครั้งแรกกับ new จะดำเนินการตามปกติ แต่ทุกครั้งต่อไปกับ new จะกลับมาเป็นครั้งแรกoptions เป็นวัตถุที่จะรวมกับตัวเลือกเมื่ออินสแตนซ์register คุณสมบัติภายในคุณสมบัติตัว options จะเพิ่มอินสแตนซ์โดยอัตโนมัติลงในเครื่องมือรีจิสทรีด้วยค่า register เป็นคีย์_super( parameters ) ภายในวิธีการจะเรียกวิธีการที่พ่อแม่ overrided // Inherit from Abstract
P . Components . Custom_Class = P . Core . Abstract . extend (
{
construct : function ( )
{
console . log ( 'Welcome to my custom class' ) ;
}
} ) ;
var custom_class = new P . Components . Custom_Class ( ) ; P . Components . Custom_Class = P . Core . Abstract . extend (
{
// Options with random deep properties
options :
{
test :
{
foo : 'bar' ,
lorem : 'ipsum'
}
} ,
// Add options argument
construct : function ( options )
{
// Pass options to _super
this . _super ( options ) ;
console . log ( 'Options' , this . options ) ;
}
} ) ;
// Instantiate by passing different options
var custom_class = new P . Components . Custom_Class ( {
test :
{
lorem : 'dolores'
}
} ) ; // Currently, static functionnality is only used for tools
// It's just a matter of organization, do whatever you want.
P . Tools . Custom_Class = P . Core . Event_Emitter . extend (
{
// Chose a name never used
static : 'custom_tool' ,
construct : function ( )
{
// Don't forget the _super
this . _super ( ) ;
console . log ( 'Init' ) ;
}
} ) ;
// 'custom_class' and 'custom_class_again' will share the same instance
// 'construct' will be called only the first time
var custom_class = new P . Tools . Custom_Class ( ) ,
custom_class_again = new P . Tools . Custom_Class ( ) ; // Create any class you'd like
P . Components . Test_Class = P . Core . Abstract . extend ( { } ) ;
// Instantiate and specify the register property in options object
// The value is the key you want to retrieve the instance later
var test_class = new P . Components . Test_Class ( { register : 'my_key' } ) ;
// Instantiate the registry tools and get the test_class using the register key
var registry = new P . Tools . Registry ( ) ,
test_class_2 = registry . get ( 'my_key' ) ; P.Core.Event_Emitter ขยาย P.Core.Abstract ด้วยวิธีการกิจกรรมพิเศษ
on off และ trigger วิธีการevent-name == eventname == event_name ) // Create a custom component that extends Event_Emitter
P . Components . Custom_Component = P . Core . Event_Emitter . extend (
{
construct : function ( )
{
this . _super ( ) ;
// Save context
var that = this ;
// Interval every seconds
window . setInterval ( function ( )
{
// Trigger event and pass parameters
that . trigger ( 'event-test' , [ 'test-1' ] ) ;
} , 1000 ) ;
}
} ) ;
var custom_component = new P . Components . Custom_Component ( ) ;
// Listen to 'event-text'
custom_component . on ( 'event-test' , function ( value )
{
// Will log 'text-1' every second
console . log ( value ) ;
} ) ; // Create a custom component that extends Event_Emitter
P . Components . Custom_Component = P . Core . Event_Emitter . extend (
{
construct : function ( )
{
this . _super ( ) ;
// Save context
var that = this ;
// Wait a second
window . setTimeout ( function ( )
{
// Trigger some events
that . trigger ( 'event-1' , [ 'test-1' ] ) ;
that . trigger ( 'event-2' , [ 'test-2' ] ) ;
that . trigger ( 'event-3' , [ 'test-3' ] ) ;
that . trigger ( 'event-4' , [ 'test-4' ] ) ;
} ) ;
}
} ) ;
// Try to instantiate twice but get a common object each time
var custom_component = new P . Components . Custom_Component ( ) ;
// Listen two events
custom_component . on ( 'event-1 event-2' , function ( value )
{
console . log ( value ) ;
} ) ;
// Stop listening to 'event-1' event
custom_component . off ( 'event-1' ) ;
// Listen to event with namespace
custom_component . on ( 'event-2.foo event-3.bar event-4.bar' , function ( value )
{
console . log ( value ) ;
} ) ;
// Stop listening on 'event-2' with 'foo' namespace
custom_component . off ( 'event-2.foo' ) ;
// Stop listening on every events with 'bar' namespace
custom_component . off ( '.bar' ) ;P.JS มาพร้อมกับเครื่องมือที่ทำไว้ล่วงหน้า แต่ละคนเป็นซิงเกิล (คงที่) คุณสามารถสร้างอินสแตนซ์ได้หลายครั้งคุณจะได้รับอินสแตนซ์แรกเสมอ
คุณสามารถขยายเครื่องมือเหล่านั้นได้หากคุณต้องการ
เบรกพอยต์ทำงานได้เล็กน้อยเช่นความกว้างและความสูงสำหรับการสืบค้นสื่อ ระบุจุดพักบางอย่างและจะก่อให้เกิดเหตุการณ์เมื่อปรับขนาด Viewport
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
breakpoints : [ // Breakpoints
{
name : 'large' ,
width :
{
value : 960 ,
extreme : 'min' ,
included : false
}
} ,
{
name : 'medium' ,
width :
{
value : 960 ,
extreme : 'max' ,
included : true
}
} ,
{
name : 'small' ,
width :
{
value : 500 ,
extreme : 'max' ,
included : true
} ,
height :
{
value : 500 ,
extreme : 'max' ,
included : true
}
}
]
}คุณสมบัติ
วิธีการ
breakpoints (วัตถุ | อาร์เรย์) เพิ่มหนึ่งเป็นจุดพักหลายจุดsilent (เป็นทางเลือกบูลีนค่าเริ่มต้น: จริง) ไม่ควรเรียกเหตุการณ์breakpoints (สตริง | อาร์เรย์) ลบหนึ่งเป็นจุดพักหลายจุดตามชื่อsilent (เป็นทางเลือกบูลีนค่าเริ่มต้น: เท็จ) ไม่ควรทริกเกอร์เหตุการณ์breakpoint (สตริง) หากเบรกพอยต์ทำงานอย่างไม่หยุดยั้งcondition (สตริง) ดำเนินการต่อไปยัง MatchMedia คลาสสิก แต่จะส่งคืนบูลีนเท่านั้นเหตุการณ์
breakpoints (อาร์เรย์) ที่ใช้งานอยู่ในปัจจุบัน ช่วยคุณแปลงสตริงเป็นสีที่เกิดขึ้นดี
สร้างรุ้งสวย -
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
gradients :
{
parse : true , // Automatically parse, looking for text to convert to gradient
target : document . body , // Default target when parsing
classes :
{
to_convert : 'gradient-text' , // Searched class
converted : 'gradient-text-converted' // Converted class
}
}
}คุณสมบัติ
วิธีการ
input วัตถุ RGB (สตริง) อะไรก็ได้ที่ดูเหมือนสี (#ff0000,#f00, สีแดง, {r: 1, g: 0, b: 1}, {h: 1, s: 1, l: 0.5})target (ไม่บังคับองค์ประกอบ DOM, ค่าเริ่มต้น: document.body)selector (สตริง, ค่าเริ่มต้น: 'to-resize')start (ใด ๆ )end (และ)count (หมายเลข)format (ไม่บังคับ, สตริง, ค่า: 'rgb' | 'hsl' , ค่าเริ่มต้น: 'hsl' )input (Object) วัตถุ RGBinput RGB (วัตถุ) HSLเหตุการณ์
ไม่มี
ใช้ CSS กับองค์ประกอบเป้าหมายและเพิ่มคำนำหน้าโดยอัตโนมัติ คุณสมบัติจะถูกจัดตั้งขึ้นโดยอัตโนมัติ
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
prefixes : [ 'webkit' , 'moz' , 'o' , 'ms' , '' ] // Default prefixes
}คุณสมบัติ
ไม่มี
วิธีการ
target (องค์ประกอบ DOM | jQuery) ที่ดึงมาพร้อมกับตัวดึงข้อมูลคลาสสิกเช่น querySelector หรือ jQueryvalues (วัตถุ) ค่าที่จะใช้prefixes (ตัวเลือกบูลีน | อาร์เรย์) จริงสำหรับคำนำหน้าเริ่มต้นหรือคำนำหน้าอาร์เรย์เหตุการณ์
ไม่มี
ให้ข้อมูลเช่นเครื่องยนต์เบราว์เซอร์ระบบและคุณสมบัติ
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
targets : [ 'html' ] // Add detected informations to targets in array (selector or DOM Elements)
}คุณสมบัติ
ie (หมายเลข)gecko (หมายเลข)webkit (หมายเลข)khtml (หมายเลข)opera (หมายเลข)version (หมายเลข)ie (หมายเลข)firefox (หมายเลข)safari (หมายเลข)konq (หมายเลข)opera (หมายเลข)chrome (หมายเลข)version (หมายเลข)windows (บูลีน)mac (บูลีน)osx (บูลีน)iphone (บูลีน)ipod (บูลีน)ipad (บูลีน)ios (บูลีน)blackberry (บูลีน)android (บูลีน)opera_mini (บูลีน)windows_mobile (บูลีน)wii (บูลีน)ps (บูลีน)touch (บูลีน)media_query (บูลีน)วิธีการ
ไม่มี
เหตุการณ์
ไม่มี
ส่งข้อมูลไปยัง Google Analytics โดยใช้อินสแตนซ์ปัจจุบัน คุณต้องยกตัวอย่าง Google Analytics ด้วยตัวเอง
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
send : true , // Should send informations
parse : true , // Automatically parse
true_link_duration : 300 , // Wait duration before following the link (enough time to be sure that informations have been well stend)
target : document . body , // Default target when parsing
classes :
{
to_tag : 'tag' , // Search class
tagged : 'tagged' // Tagged class
} ,
logs :
{
warnings : false , // Log warning
send : false // Log sent informations
}
}คุณสมบัติ
ไม่มี
วิธีการ
target (ไม่บังคับองค์ประกอบ DOM, ค่าเริ่มต้น: document.body)selector (สตริง, ค่าเริ่มต้น: 'to-resize')datas (วัตถุ)category (ใด ๆ )action (ใด ๆ )label (ไม่บังคับ)value (ไม่บังคับใด ๆ )unique (ไม่ควรส่งสตริง) ไม่ควรส่งข้อมูลมากกว่าหนึ่งครั้ง (ขึ้นอยู่กับค่าสตริง)เหตุการณ์
วิธีการคุณสมบัติและเหตุการณ์ที่เป็นญาติกับคีย์บอร์ด
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
ไม่มี
คุณสมบัติ
วิธีการ
input (หมายเลข) ปุ่มกดinput (สตริง | หมายเลข) ปุ่มหรืออักขระinputs (อาร์เรย์) ปุ่มกดและ/หรืออักขระเหตุการณ์
keycode (หมายเลข)character (สตริง)keycode (หมายเลข)character (สตริง) รู้ว่าเมื่อใดที่ผู้ใช้ของคุณใช้รหัส Konami ↑↑↓←→←→ BA
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
reset_duration : 1000 , // Time in before reseting
sequence : // Sequence to enter
[
'up' ,
'up' ,
'down' ,
'down' ,
'left' ,
'right' ,
'left' ,
'right' ,
'b' ,
'a'
]
}คุณสมบัติ
ไม่มี
วิธีการ
ไม่มี
เหตุการณ์
index (int) ความคืบหน้าก่อนหมดเวลาindex (int) ความคืบหน้าก่อนล้มเหลว คุณสมบัติและเหตุการณ์ที่เป็นญาติกับเมาส์
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
ไม่มี
คุณสมบัติ
วิธีการ
ไม่มี
เหตุการณ์
position (วัตถุ) ข้อมูลตำแหน่งเมาส์target (องค์ประกอบ DOM) โดยตรงภายใต้ตำแหน่งเมาส์false ในการโทรกลับposition (วัตถุ) ข้อมูลตำแหน่งเมาส์target (องค์ประกอบ DOM) โดยตรงภายใต้ตำแหน่งเมาส์position (วัตถุ) ข้อมูลตำแหน่งเมาส์target (องค์ประกอบ DOM) โดยตรงภายใต้ตำแหน่งเมาส์wheel (วัตถุ) ของเมาส์false ในการโทรกลับ รีจิสทรีคีย์/ค่าสำหรับเมื่อคุณต้องการจัดเก็บตัวแปรและดึงข้อมูลได้ทุกที่โดยไม่ต้องใช้ตัวแปรทั่วโลกที่น่าเกลียด
คุณอาจใช้กับตัวแปรแคช
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
ไม่มี
คุณสมบัติ
วิธีการ
key (สตริง)callback (ไม่จำเป็นต้องใช้ฟังก์ชัน) เรียกว่าหากไม่พบรายการสำหรับคีย์ที่ระบุและผลลัพธ์ที่ส่งคืนkey (สตริง)value (ใด ๆ )เหตุการณ์
key (สตริง)value (ใด ๆ ) ปรับขนาดองค์ประกอบภายในคอนเทนเนอร์ตามตัวเลือกที่เป็นไปได้มากมาย
อาจแยกวิเคราะห์และปรับขนาดโดยอัตโนมัติตามคลาสและแอตทริบิวต์ในคอนเทนเนอร์
ในการทำงานคุณจะต้องระบุคุณสมบัติต่อไปนี้ในองค์ประกอบ DOM ด้วยตนเอง
data-width | width (ไม่บังคับหมายเลข)data-height | height (ไม่บังคับหมายเลข)data-width | width (หมายเลข)data-height | height (หมายเลข)data-fit-type (ไม่บังคับ, สตริง, ค่า: 'เติม' | 'พอดี' , ค่าเริ่มต้น: 'เติม' )data-align-x (ไม่บังคับ, สตริง, ค่า: 'ซ้าย' | 'center' | 'ขวา' , ค่าเริ่มต้น: 'center' )data-align-y (ไม่บังคับ, สตริง, ค่า: 'top' | 'center' | 'ล่าง' , ค่าเริ่มต้น: 'center' )data-rounding (ไม่บังคับ, สตริง, ค่า: 'Ceil' | 'Floor' | 'Round' | ไม่มี, ค่าเริ่มต้น: 'Ceil' ) ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
force_style : true , // Add 'position' and 'overflow' CSS properties if not set yet
parse : true , // Automatically parse
target : document . body , // Default target when parsing
auto_resize : true , // Resize on browser 'resize' event
classes :
{
to_resize : 'to-resize' , // Containers searched class (on the container)
content : 'content' // Content class (must be inside container)
}
}คุณสมบัติ
ไม่มี
วิธีการ
target (ไม่บังคับองค์ประกอบ DOM, ค่าเริ่มต้น: document.body)selector (สตริง, ค่าเริ่มต้น: 'to-resize')container (องค์ประกอบ DOM)content (องค์ประกอบ DOM)force_style (ไม่บังคับบูลีน, ค่าเริ่มต้น: จริง) เพิ่มคุณสมบัติสไตล์ 'ตำแหน่ง' และ 'โอเวอร์โฟลว์' หากยังไม่ได้ตั้งค่าparameters (วัตถุ)content_width (หมายเลข)content_height (หมายเลข)container_width (หมายเลข)container_height (หมายเลข)fit_type (ไม่บังคับ, สตริง, ค่าเริ่มต้น: เติม , ค่า: เติม | FIT )align_x (ไม่บังคับ, สตริง, ค่าเริ่มต้น: กลาง , ค่า: ซ้าย | กลาง | ขวา )align_y (ไม่บังคับ, สตริง, ค่าเริ่มต้น: กลาง , ค่า: ด้านบน | กลาง | ด้านล่าง )rounding (ไม่บังคับ, สตริง, ค่าเริ่มต้น: เพดาน , ค่า: เพดาน | ชั้น | รอบ | ไม่มี)format (เป็นทางเลือก, สตริง, ค่าเริ่มต้น: ทั้งคู่ , ค่า: ทั้งสอง | CARTESIAN | CSS )เหตุการณ์
ไม่มี
วิธีการจัดการสตริง
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
ไม่มี
คุณสมบัติ
ไม่มี
วิธีการ
value (สตริง) ที่จำเป็นต้องเปลี่ยนกรณีformat (สตริง) กรณีที่ต้องการvalue (สตริง) สตริงเพื่อตัดแต่งcharacters (สตริง) อักขระเพื่อตัดแต่งvalue (สตริง) แปลงเป็นบูลีนอย่างชาญฉลาดด้วยภาษาที่รองรับมากมายvalue (สตริง) สตริงเป็น slugifyเหตุการณ์
ไม่มี
เรียกใช้ทิกเกอร์ที่เรียกเหตุการณ์แต่ละเฟรมฐานบน RequestAnimationFrame
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
auto_run : true
}คุณสมบัติ
start เมื่อใดที่ ticker เริ่มล่าสุดelapseddelta ที่ใช้ไปตั้งแต่เห็บสุดท้ายcurrentวิธีการ
run (บูลีน) ควรเริ่มใช้ตัวจับเวลาframes_count (หมายเลข)action (ฟังก์ชั่น)after (ไม่บังคับบูลีนค่า: จริง | เท็จ , ค่าเริ่มต้น: จริง ) ควรใช้ฟังก์ชั่นหลังจากเหตุการณ์ tick ถูกทริกเกอร์เหตุการณ์
time (วัตถุ) เวลาtime (วัตถุ) เวลา ให้ข้อมูลเกี่ยวกับวิวพอร์ตเช่นความกว้างความสูง, ม้วนเลื่อน, เลื่อนซ้าย, เดลต้าเลื่อน ฯลฯ
กระตุ้นเหตุการณ์ในการเลื่อนและปรับขนาด
สามารถปิดการวางตัวบนสกรอลล์เพื่อปรับปรุงประสิทธิภาพ
ดูรหัส
ดูตัวอย่าง
ตัวเลือก
{
disable_hover_on_scroll : false , // Improve performance when scrolling but disable hovers
initial_triggers : [ 'resize' , 'scroll' ] // On the next frame, triggers 'resize' then 'resize' events
}คุณสมบัติ
delta (วัตถุ)top | y (หมายเลข) Scroll Delta ด้านบนleft | x (หมายเลข) เลื่อนเดลต้าซ้ายdirection (วัตถุ)y (สตริง) ทิศทางการเลื่อนแนวตั้งx (สตริง) ทิศทางการเลื่อนแนวนอนวิธีการ
condition (สตริง) ดำเนินการต่อไปยัง MatchMedia คลาสสิก แต่จะส่งคืนบูลีนเท่านั้นเหตุการณ์
viewport (วัตถุ)viewport (วัตถุ) Preferences > Browse Packages...User/ โฟลเดอร์BC : คลาส PAN
P . Components . Class = P . Core . Abstract . extend (
{
static : 'class' ,
options : { } ,
construct : function ( options )
{
this . _super ( options ) ;
}
} ) ;BCS : PAN Class เข้มงวด
( function ( )
{
'use strict' ;
P . Components . Class = P . Core . Abstract . extend (
{
static : 'class' ,
options : { } ,
construct : function ( options )
{
this . _super ( options ) ;
}
} ) ;
} ) ( ) ;BFN : ฟังก์ชั่น PAN
/**
* Description
*/
name : function ( options )
{
var that = this ;
this . _super ( ) ;
}BN : แพนใหม่
new Pan . Namespace . Class ( ) ;BNC : PAN ใหม่ส่วนประกอบ
new Pan . Components . Class ( ) ;BNT : เครื่องมือใหม่ PAN
new Pan . Tools . Class ( ) ; convert_case ด้วย dashed add_detector none ในการปัดเศษ init โดย construct$ Property บนบทคัดย่อp- ในคลาสเริ่มต้นnull'use strict' ทั่วไปทั่วไปmatch_breakpoint ใน viewportno-features ไม่ทำงานกับเครื่องตรวจจับformat บนวิธี get_sizes (สนับสนุน "คาร์ทีเซียน", "CSS" หรือ "ทั้งสอง")wait การเริ่มต้น