ÿØÿà JFIF    ÿÛ „  ( %!1"%)+...383-7(-.+  -%%--------+------------/----------------------------ÿÀ  ¶" ÿÄ     ÿÄ @    !1AQaq‘¡"±ÁÑð2’BRráS‚ñ3b¢CT²Ò #cÿÄ    ÿÄ '   1!AQ2a"‘±#ÿÚ   ? ò(/p‘—–¢·,M|¯G»R£üešT. ôŸEoCFñ‡ 4ÔkåóxR|µÁ¨ÓDà!Ç´µ˜‡p ÍQ‹§!þž^õWsŒy  åÁ§$á«%ºq˜™JyyË0y«^Ϗ -3ÃÏËÈ£Æ\P’ä„s&•‹Üs üô'àWt¹pñCp$bÚF`·7.^)¾!)ÒÙ˜–ÅÏš^h¾ø³·ìe±ŒaeÖ—Í,e=B}Jéߦ$$½—šÙÜCC¯¶è8β–Åkèwx LÉngT±æ¹£Ócœ¿Í/©Éÿ ‰ÚCÒ­mq;Tt¶–}0"zÖPcd1š­¤tˆ„ÐÓâqú[™öUCŠ2޿د­É(¸ßúçšmW,Ò ºf‹Ån™ÄLêÁ8üÁkÁ€L¥ÍuJ1œôrÂSŒÓöt!7EUíïb)AËi¬â-ÙHk8òÁiXYwÅ)O^"ÇØriÛô{»wRUKÙÏÚlÓ¬€‚’שT ] ªb—ÊîKC^×M“xùäñz¬zJ× {4[¹M'IÆeH1LCWÕ]œûº WDæà°OÅ‚¹c²ÞuA–rL`HšpCez‡V’— Ž‚Ë„–ñ­'µR0ÕÖ=À:±G»C\nÆÉ5*¢ †3šhQ4ýÒi$Õ1"Ü]¢p-q3zcQ$ªö¨¥æf›‘»´ÝÚHá„e²JÇ–iÊ:·à¬Øc5Åk»Laª*wi [0Ówk ¦a¦0Õ²ÅÅ‚T¸’³q:Æ<¹ú Ò˜Æ}2VE•Ѐp¡Ô3Úº …h³^LJºçì¥Ánó|˜ÖˆÎˆ+« ¦dø‘Mº–d\ªDðÛ„Ì×LÝ——Ð9Ç|•FèçVm™¨€™3õS–9Äå¢<̉Ìm¢±`·º˜&Z²ž Ë®D«¶»6™‰©­HÈ Àá«h­i³04æ’hxœi3ï¨(ÓL·†‹¶ËpŒ ƒÜÒ? :õdsÀ –3æÓ·Üjâ¬9—]8n¼&]I F£¼…ì–—Œ0v°LǐÅfÛ2TÖ’aµ˜N@ÖBSÏ^à´4-±°b×nÈÈœÆD=KdŒø…ÄÈK,›ÖR§fjü$^ÔÎ!„6^ s:Üun\ôkCÞò÷<—Lúl Í›G¹ÀPá¼Nc¡šÒ…ÙWͳœ±vÊáЄ×9‹P‰cEØ‘™›µŸP<×g1 º©Ø¬wiÁ^l5× I/';Ë+´Z‡ÓÄFÕp[Èð’ HÄ ó 9¬Dl4“é±Ï”V=^Hð;žLädÉa‚°Ë,#/Ž~²BÔÛ QãñQtIeórVB,ÏÂf‹4#Μc‹É3ZIÖ Œ¢¥·üxa‡Ãçè„jŠ[5 Ä!U?,3žÎ×…ðdÓ÷háŠA‰ìÄ4÷ÃÜZÃE{‰®+W\ZÍE[‰»µk»MÝ­`¢©†˜ÃV‹-f¢¡†¢a«eŠ%«Y¨©q%jâd,Ôq`) ¤¦…šˆ ¦E>0Ùb²t–Ÿ  ÷jsςҒKÈcø(é›;k(’#ôŒQ ™C> õ³M9óºÆµ¤çâ;uÀ)5>RÔ¸fÓ~Ȧ—’-$fe«"FâUˆÊwµPÏu w+"åÉó¨6s™Û9(À¨ù©hE°½†n`m~“@©›p!Vkhµ Á1šbEqqÊ@ºèl›2 –Yã%‘‚hÛ{a¶‡ÅÞM²¬çL34®Çl]®‹ŽØŒm'RÜe35æöˆ­Á­ cP9šeÁköo´L³Ì=p8]”‡B¶,šº|ɏdzXˆØk*ÇÚ{#ñ‰pã(€¶‡9ý'šÜ³½¯kƒ†Â’ëSOƒ•Å®H6+a¢µˆ‹Y¨b˜b+XˆÖ!°u!¢"µˆˆn2ˆ Å0Ä`Å Ô®c(ÓÜGº•Ä»Œ âWî%q.áÐÄ÷î%umÍ£+ÜQ,Vn¦-GphU¸¢X­&,Gt ·K¢ÅÅ·¥RÄÊÉbKn N­R2g$VµÕó Qr#–ÓZUÏð0ÎtÙÀœz ëöo“Îk¯n„T°"SÞ+³/…€½"ižãO%Í%&Δâ‘ËØ´IˆÓ°Ë‰ÞM3.™yçÁzit›`4C`k¢¼á!álÄï sÂ[×!¤l¾æo"ƒIÔ'@ªu)3›ô®“@Z à¾] üœ'‡4¸PÞkÁ-qÄH‰ÓÍBd´ÿ —¹°ÄA&ÊUC„öz‚‚RæŠtf¬>˜ÑidšEçÑL÷áý¡V±h§­c¿¥¨ƒ@g¼…Ýö^ÞËc.ž„æ“I[ ª+·zÐÒÚ,½Ð»¶€C›7jk$๖€Ž¾ÅÙpp¶ÍþéΤ ½ØÎŒq ñpæžÅ¥#Øâ49ÃÂK^MYV“,¶Éz_òæ:…;Õ«¦I3âJ£¤û5$7Èxün\â]Êe¯(Ÿ&Ž‹¶2<6Ćf× æ¢ƱqWı[(ÙÂŽç‚T7¨@ÈÉÍß‚ïÙ"&3TYlGށ†)†#5ŠA©^T2ÆÁ†)©†©†¤yGXÁ†©"†)©¼ÅV WS†#©]R–r‹q5ÕbâWþBh¯u+ªÅÄ×ü„nÑ^êkªÁj‰jeœWˆÕÕ`µDµ2Ì+Ä µDµµ5Ô{¤Þ0RF’H÷AÛ<ÊÁ§ ƈæ0Ñ£ê4 öÚµ[¬/1²€â<-¬šö²r×0o×w ´xÐÒË„ g01¬„åEM蛇Ã\6µE›‘fÙO k÷CºnÓ1`iîÒ² áÂ!ÑLÄÿ ³¬\õ*:M=Ç»c‹2[‰ØsÕLò\ŒK L^™üÄN\¶#» Ç\……ßïIœÉ$¸ÎñÍ®ÔHÇ Ûí/´>Li”„†g^$ 7NÍÑÑ2M2ªNg=k½Ð}Ÿl6‡ —JWˆ”ÞéT·+µ¦üÂFè¢Vs6ýÆ4»2+2IÝ9ô9®ÇGÙÇ1+Ä8;*Õ§ž½D*îÑWÚçá3Ma¤·ˆ¥t}š²Ü…Q+Æüµ8HíS”üxGéÁˆ¦Ël„éÈ 5 µÄƒ6äÜ(kIš¯S†fÖ&¸®×v|Äyˆ*禌Éù@7-®Ä[]ÎÖ¿ê`º…=:…žJVnݳvðÖKE¼‚ »mà ÷f®:Ë ™–4rð¡4` ܹçž~‹C=œ…¾Ïj|VDtK.ƒ"9 Ï ­–éXá³6WÒïIL-Ї Ç PKr\tn55 M_videos.phpnu[db->select('id, post_title, post_content, is_deleted'); $this->db->where('post_type', 'video'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('post_title', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get Videos * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_videos($limit = 0, $offset = 0) { $this->db->select('id, post_title, post_content'); $this->db->where('post_type', 'video'); $this->db->where('is_deleted', 'false'); $this->db->order_by('created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } } PKr\jmu u M_admission_phases.phpnu[db->select('x1.id, x1.phase_name, x2.academic_year, x1.phase_start_date, x1.phase_end_date, x1.is_deleted'); $this->db->join('academic_years x2', 'x1.academic_year_id = x2.id', 'LEFT'); if ( ! empty($keyword) ) { $this->db->like('x1.phase_name', $keyword); $this->db->or_like('x2.academic_year', $keyword); $this->db->or_like('x1.phase_start_date', $keyword); $this->db->or_like('x1.phase_end_date', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get Current Phase / Gelombang Pendaftaran * @return Array */ public function get_current_phase() { $query = $this->db ->select('id, phase_name, phase_start_date, phase_end_date') ->where('CURDATE() >= phase_start_date') ->where('CURDATE() <= phase_end_date') ->where('is_deleted', 'false') ->order_by('phase_start_date', 'DESC') ->limit(1) ->get(self::$table); if ($query->num_rows() === 1) { $res = $query->row(); return [ 'id' => $res->id, 'phase_name' => $res->phase_name, 'phase_start_date' => $res->phase_start_date, 'phase_end_date' => $res->phase_end_date ]; } return []; } /** * Dropdown * @return Array */ public function dropdown() { $query = $this->db ->select('id, phase_name') ->where('is_deleted', 'false') ->order_by('phase_name', 'DESC') ->get(self::$table); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = $row->phase_name; } } return $dataset; } } PKr\^r M_class_groups.phpnu[db->select(" x1.id , CONCAT(x1.class_group, IF((x2.major_short_name <> ''), CONCAT(' ',x2.major_short_name),''),IF((x1.sub_class_group <> ''),CONCAT(' - ',x1.sub_class_group),'')) AS class_name , x1.is_deleted "); $this->db->join('majors x2', 'x1.major_id = x2.id', 'LEFT'); if ( ! empty($keyword) ) { $this->db->like("CONCAT(x1.class_group, IF((x2.major_short_name <> ''), CONCAT(' ',x2.major_short_name),''),IF((x1.sub_class_group <> ''),CONCAT(' - ',x1.sub_class_group),''))", $keyword); } $this->db->order_by('x1.class_group', 'ASC'); $this->db->order_by('x1.major_id', 'ASC'); $this->db->order_by('x1.sub_class_group', 'ASC'); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Dropdown * @return Array */ public function dropdown() { $query = $this->db ->select("x1.id, CONCAT(x1.class_group, IF((x2.major_short_name <> ''), CONCAT(' ',x2.major_short_name),''),IF((x1.sub_class_group <> ''),CONCAT(' - ',x1.sub_class_group),'')) AS class_name") ->join('majors x2', 'x1.major_id = x2.id', 'LEFT') ->where('x1.is_deleted', 'false') ->order_by('x1.class_group', 'ASC') ->order_by('x1.major_id', 'ASC') ->order_by('x1.sub_class_group', 'ASC') ->get(self::$table. ' x1'); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = $row->class_name; } } return $dataset; } } PKr\ EyyM_employees.phpnu[db->select(" x1.id , x1.nik , x1.full_name , x2.option_name AS employment_type , IF(x1.gender = 'M', 'L', 'P') AS gender , COALESCE(x1.birth_place, '') birth_place , x1.birth_date , x1.photo, x1.is_deleted "); $this->db->join('options x2', 'x1.employment_type_id = x2.id', 'LEFT'); if ( ! empty($keyword) ) { $this->db->like('x1.nik', $keyword); $this->db->or_like('x1.full_name', $keyword); $this->db->or_like('x1.gender', $keyword); $this->db->or_like('x1.birth_place', $keyword); $this->db->or_like('x1.birth_date', $keyword); $this->db->or_like('x2.option_name', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Dropdown * @return Array */ public function dropdown() { $query = $this->db ->select('id, nik, full_name') ->where('is_deleted', 'false') ->order_by('full_name', 'ASC') ->get(self::$table); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = $row->nik .' - '. $row->full_name; } } return $dataset; } /** * Get Employment Type * @param Integer $id * @return String */ public function get_employment_type($id) { $query = $this->model->RowObject(self::$pk, $id, self::$table); if (is_object($query)) { $employment_type = $this->model->RowObject('id', $query->employment_type_id, 'options'); if (is_object($employment_type)) { return $employment_type->option_name; } return NULL; } return NULL; } /** * Get Inactive Accounts * @return Resource */ public function get_inactive_accounts() { $this->db->select('x1.id, x1.nik, x1.full_name, x1.email'); $this->db->join('users x2', 'x1.id = x2.user_profile_id AND x2.user_type = "employee"', 'LEFT'); $this->db->where('x2.user_profile_id', NULL); $this->db->where('x1.is_deleted', 'false'); return $this->db->get('employees x1'); } /** * Employee Query * @return String */ public function employee_query() { return " SELECT x1.id , x1.assignment_letter_number , x1.assignment_letter_date , x1.assignment_start_date , x1.parent_school_status , x1.full_name , IF(x1.gender = 'M', 'L', 'P') AS gender , x1.nik , x1.birth_place , x1.birth_date , x1.mother_name , x1.street_address , x1.rt , x1.rw , x1.sub_village , x1.village , x1.sub_district , x1.district , x1.postal_code , x2.option_name AS religion , x3.option_name AS marriage_status , x1.spouse_name , x4.option_name AS spouse_employment , x1.citizenship , x1.country , x1.npwp , x5.option_name AS employment_status , x1.nip , x1.niy , x1.nuptk , x6.option_name AS employment_type , x1.decree_appointment , x1.appointment_start_date , x7.option_name AS institution_lifter , x1.decree_cpns , x1.pns_start_date , x8.option_name AS 'rank' , x9.option_name AS salary_source , x1.headmaster_license , x10.option_name AS laboratory_skill , x11.option_name AS special_need , x1.braille_skills , x1.sign_language_skills , x1.phone , x1.mobile_phone , x1.email , x1.photo FROM employees x1 LEFT JOIN options x2 ON x1.religion_id = x2.id LEFT JOIN options x3 ON x1.marriage_status_id = x3.id LEFT JOIN options x4 ON x1.spouse_employment_id = x4.id LEFT JOIN options x5 ON x1.employment_status_id = x5.id LEFT JOIN options x6 ON x1.employment_type_id = x6.id LEFT JOIN options x7 ON x1.institution_lifter_id = x7.id LEFT JOIN options x8 ON x1.rank_id = x8.id LEFT JOIN options x9 ON x1.salary_source_id = x9.id LEFT JOIN options x10 ON x1.laboratory_skill_id = x10.id LEFT JOIN options x11 ON x1.special_need_id = x11.id WHERE 1 = 1"; } /** * Employee Reports * @return Resource */ public function employee_reports() { $query = $this->employee_query(); $query .= " ORDER BY x1.full_name ASC"; return $this->db->query($query); } /** * Profile * @param Integer $id * @return Resource */ public function profile($id) { $query_string = $this->employee_query(); $query_string .= ' AND x1.id = ? '; return $this->db->query($query_string, [_toInteger( $id )])->row(); } /** * Get Employees * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_employees($limit = 0, $offset = 0) { $this->db->select(" x1.id , x1.nik , x1.full_name , IF(x1.gender = 'M', 'Laki-laki', 'Perempuan') as gender , x1.birth_place , x1.birth_date , x1.photo , x2.option_name AS employment_type "); $this->db->join('options x2', 'x1.employment_type_id = x2.id', 'LEFT'); $this->db->where('x1.is_deleted', 'false'); $this->db->order_by('x1.full_name', 'ASC'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Check if nik exists * @param String $nik * @param Integer $id * @return Boolean */ public function nik_exists( $nik, $id = 0 ) { $this->db->where('nik', $nik); if ( _isNaturalNumber($id) ) $this->db->where('id <>', _toInteger($id)); $this->db->where('is_deleted', 'false'); $count = $this->db->count_all_results(self::$table); return $count > 0; } /** * Check if email exists * @param String $email * @param Integer $id * @return Boolean */ public function email_exists( $email, $id = 0 ) { $this->db->where('email', $email); if ( _isNaturalNumber($id) ) $this->db->where('id <>', _toInteger($id)); $this->db->where('is_deleted', 'false'); $count = $this->db->count_all_results(self::$table); return $count > 0; } } PKr\A6LLM_image_sliders.phpnu[db->select('id, caption, image, is_deleted'); if ( ! empty($keyword) ) $this->db->like('caption', $keyword); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get All Image Sliders * @param Integer $limit * @return Resource */ public function get_image_sliders($limit = 0) { $this->db->select('id, caption, image'); $this->db->where('is_deleted', 'false'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table); } } PKr\`r r M_menus.phpnu[db ->select('id, menu_title, menu_url, menu_type, is_deleted') ->order_by('menu_parent_id', 'ASC') ->order_by('menu_position', 'ASC') ->get(self::$table); } /** * Fungsi untuk menu recursive : TOP Navigasi * @param Integer $menu_parent_id * @return Array */ public function nested_menus($menu_parent_id = 0) { $menu = []; $this->db->select('id, menu_title, menu_url, menu_target, menu_type'); $this->db->where('menu_parent_id', $menu_parent_id); $this->db->where('is_deleted', 'false'); $this->db->order_by('menu_position', 'ASC'); $this->db->order_by('menu_title', 'ASC'); $query = $this->db->get(self::$table); foreach ($query->result() as $row) { $menu[] = [ 'id' => $row->id, 'menu_title' => $row->menu_title, 'menu_url' => $row->menu_url, 'menu_target' => $row->menu_target, 'menu_type' => $row->menu_type, 'children' => $this->nested_menus($row->id), ]; } return $menu; } /** * Recursive function for save menu position * @param Integer $menu_parent_id * @param Integer $children * @return Void */ public function save_menu_position($menu_parent_id, $children) { if ( ! is_null($children) ) { $i = 1; foreach ($children as $key => $value) { $id = $children[$key]['id']; $dataset = [ 'menu_parent_id' => $menu_parent_id, 'menu_position' => $i ]; $this->db->where(self::$pk, $id)->update(self::$table, $dataset); if (isset($children[$key]['children'][0])) { $this->save_menu_position($id, $children[$key]['children']); } $i++; } } } } PKr\hgM_buildings.phpnu[db->select('id, building_name, is_deleted'); if ( ! empty($keyword) ) $this->db->like('building_name', $keyword); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Dropdown * @return Array */ public function dropdown() { $query = $this->db ->select('id, building_name') ->where('is_deleted', 'false') ->order_by('building_name', 'DESC') ->get(self::$table); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = $row->building_name; } } return $dataset; } } PKr\nWDD M_links.phpnu[db->select('id, link_url, link_title, link_target, is_deleted'); $this->db->where('link_type', 'link'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('link_url', $keyword); $this->db->or_like('link_title', $keyword); $this->db->or_like('link_target', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get All Link * @param Integer $limit * @return Resource */ public function get_links($limit = 0) { $this->db->select('id, link_title, link_url, link_target'); $this->db->where('link_type', 'link'); $this->db->where('is_deleted', 'false'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table); } } PKr\ aa M_pages.phpnu[db->select(' x1.id , x1.post_title , x2.user_full_name AS post_author , x1.created_at , x1.is_deleted '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'page'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.post_title', $keyword); $this->db->or_like('x2.user_full_name', $keyword); $this->db->or_like('x1.created_at', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get All Pages * @return Resource */ public function get_pages() { return $this->db ->select('id, post_title') ->where('post_type', 'page') ->where('is_deleted', 'false') ->get(self::$table); } } PKr\n*  M_class_group_settings.phpnu[db->select(" x1.id , x2.academic_year , CONCAT(x3.class_group, IF((x4.major_short_name <> ''), CONCAT(' ',x4.major_short_name),''),IF((x3.sub_class_group <> ''),CONCAT(' - ',x3.sub_class_group),'')) AS class_name , CONCAT(x5.nik, ' - ', x5.full_name) AS employee_name , COUNT(x6.class_group_setting_id) AS total , x1.is_deleted "); $this->db->join('academic_years x2', 'x1.academic_year_id = x2.id', 'LEFT'); $this->db->join('class_groups x3', 'x1.class_group_id = x3.id', 'LEFT'); $this->db->join('majors x4', 'x3.major_id = x4.id', 'LEFT'); $this->db->join('employees x5', 'x1.employee_id = x5.id', 'LEFT'); $this->db->join('class_group_students x6', 'x1.id = x6.class_group_setting_id', 'LEFT'); if ( ! empty($keyword) ) { $this->db->like("x2.academic_year", $keyword); $this->db->or_like("CONCAT(x3.class_group, IF((x4.major_short_name <> ''), CONCAT(' ',x4.major_short_name),''),IF((x3.sub_class_group <> ''),CONCAT(' - ',x3.sub_class_group),''))", $keyword); $this->db->or_like("x5.nik", $keyword); $this->db->or_like("x5.full_name", $keyword); } $this->db->group_by('x1.id, x1.academic_year_id, x1.class_group_id'); $this->db->order_by('x2.academic_year', 'DESC'); $this->db->order_by('x3.class_group', 'ASC'); $this->db->order_by('x3.major_id', 'ASC'); $this->db->order_by('x3.sub_class_group', 'ASC'); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } } PKr\x M_majors.phpnu[db->select('id, major_name, major_short_name, is_active, is_deleted'); if ( ! empty($keyword) ) { $this->db->like('major_name', $keyword); $this->db->or_like('major_short_name', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Count Active Majors * @return Boolean */ public function major_count() { $count = $this->db ->where('is_deleted', 'false') ->count_all_results(self::$table); return $count > 0; } /** * Dropdown * @return Array */ public function dropdown() { $query = $this->db ->select('id, major_name') ->where('is_deleted', 'false') ->where('is_active', 'true') ->get(self::$table); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = $row->major_name; } } return $dataset; } } PKr\N   M_user_privileges.phpnu[db->select('x1.id, x2.user_group, x3.module_name, x3.module_description, x3.module_url, x1.is_deleted'); $this->db->join('user_groups x2', 'x1.user_group_id = x2.id', 'LEFT'); $this->db->join('modules x3', 'x1.module_id = x3.id', 'LEFT'); if ( ! empty($keyword) ) { $this->db->like('x2.user_group', $keyword); $this->db->or_like('x3.module_name', $keyword); $this->db->or_like('x3.module_description', $keyword); $this->db->or_like('x3.module_url', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get user modules by user group id * @param Integer $user_group_id * @param String $user_type * @return Array */ public function get_user_privileges($user_group_id, $user_type) { $user_privileges = ['dashboard', 'change_password']; if ($user_type == 'administrator') { array_push($user_privileges, 'profile'); $query = $this->db ->select('x2.module_url') ->join('modules x2', 'ON x1.module_id = x2.id', 'LEFT') ->where('x1.user_group_id', $user_group_id) ->where('x1.is_deleted', 'false') ->get(self::$table.' x1'); foreach ($query->result() as $row) { array_push($user_privileges, $row->module_url); } } else if ($user_type == 'employee') { array_push($user_privileges, 'employee_profile', 'posts', 'teacher'); } else if ($user_type == 'student') { array_push($user_privileges, 'student_profile', 'scholarships', 'achievements', 'posts', 'student_presence'); } else { array_push($user_privileges, 'maintenance', 'users', 'admission', 'appearance', 'blog', 'employees', 'media', 'plugins', 'reference', 'settings', 'academic', 'profile'); } return $user_privileges; } } PKr\_< M_academic_years.phpnu[db->select('id, academic_year, semester, current_semester, admission_semester, is_deleted'); if ( ! empty($keyword) ) $this->db->like('academic_year', $keyword); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get active admission semester ID * @return Integer */ public function get_active_academic_year() { $dataset = []; $admission_semester = $this->db ->select('id, academic_year') ->where('admission_semester', 'true') ->where('is_deleted', 'false') ->order_by('academic_year', 'DESC') ->limit(1) ->get(self::$table); if ($admission_semester->num_rows() === 1) { $res = $admission_semester->row(); $dataset['admission_semester_id'] = $res->id; $dataset['admission_semester'] = $res->academic_year; $dataset['admission_year'] = substr($res->academic_year, 0, 4); } $current_semester = $this->db ->select('id, academic_year, semester') ->where('current_semester', 'true') ->where('is_deleted', 'false') ->order_by('academic_year', 'DESC') ->limit(1) ->get(self::$table); if ($current_semester->num_rows() === 1) { $res = $current_semester->row(); $dataset['current_academic_year_id'] = $res->id; $dataset['current_academic_year'] = $res->academic_year; $dataset['current_academic_semester'] = $res->semester; // $dataset['academic_year'] = $res->academic_year . ' / ' . ($res->semester == 'odd' ? 'Ganjil':'Genap'); } return $dataset; } /** * Dropdown * @return Array */ public function dropdown($short = false) { $query = $this->db ->select('id, academic_year') ->where('is_deleted', 'false') ->order_by('academic_year', 'ASC') ->get(self::$table); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = ($short ? substr($row->academic_year, 0, 4) : $row->academic_year); } } return $dataset; } /** * Deactivate Academic Years * @param Integer * @return Boolean */ public function deactivate_academic_years($id = 0, $field = 'current_semester') { if ($id > 0) $this->db->where(self::$pk . ' !=', $id); return $this->db->update(self::$table, [$field => 'false']); } } PKr\ZpS S M_scholarships.phpnu[db->select('id, scholarship_type, scholarship_description, scholarship_start_year, scholarship_end_year, is_deleted'); if (__session('user_type') === 'student') $this->db->where('student_id', __session('user_profile_id')); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('scholarship_type', $keyword); $this->db->or_like('scholarship_description', $keyword); $this->db->or_like('scholarship_start_year', $keyword); $this->db->or_like('scholarship_end_year', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get By Student ID * @param Integer $student_id * @return Resource */ public function get_by_student_id($student_id = 0) { $this->db->select('id, scholarship_type, scholarship_description, scholarship_start_year, scholarship_end_year, is_deleted'); $this->db->where('student_id', $student_id); $this->db->where('is_deleted', 'false'); return $this->db->get(self::$table); } } PKr\W11public/M_posts.phpnu[db->select(' x1.id , x1.post_title , x1.created_at , x1.post_content , x1.post_image , x1.post_slug , x1.post_counter , x2.user_full_name AS post_author '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.post_status', 'publish'); $this->db->where('x1.is_deleted', 'false'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->order_by('x1.created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table . ' x1'); } /** * Get Popular Posts * @param Integer $limit * @return Resource */ public function get_popular_posts($limit = 0) { $this->db->select(' x1.id , x1.post_title , x1.created_at , x1.post_content , x1.post_image , x1.post_slug , x1.post_counter , x2.user_full_name AS post_author '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.post_status', 'publish'); $this->db->where('x1.is_deleted', 'false'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->order_by('x1.post_counter', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table . ' x1'); } /** * Get Most Commented * @param Integer $limit * @return Resource */ public function get_most_commented($limit = 0) { $this->db->select(' x1.id , x1.post_title , x1.created_at , x1.post_content , x1.post_image , x1.post_slug , x1.post_counter , x2.user_full_name AS post_author , COUNT(x3.id) AS total_comment '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->join('comments x3', 'x1.id = x3.comment_post_id AND x3.comment_type = "post"', 'LEFT'); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.post_status', 'publish'); $this->db->where('x1.is_deleted', 'false'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->group_by(range(1, 8)); $this->db->order_by('9', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit); $this->db->having('COUNT(x3.id) > 0'); return $this->db->get(self::$table . ' x1'); } /** * Get Random Posts * @param Integer $limit * @return Resource */ public function get_random_posts($limit = 0) { $this->db->select(' x1.id , x1.post_title , x1.created_at , x1.post_content , x1.post_image , x1.post_slug , x1.post_counter , x2.user_full_name AS post_author '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.post_status', 'publish'); $this->db->where('x1.is_deleted', 'false'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->order_by('RAND()'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table .' x1'); } /** * Get Related Posts * @param String $post_categories * @param Integer $id * @return Resource */ public function get_related_posts($post_categories = '', $id = 0) { $post_categories = explode(',', $post_categories); $this->db->select(' x1.id , x1.post_title , x1.created_at , x1.post_content , x1.post_image , x1.post_slug , x1.post_counter , x2.user_full_name AS post_author '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.post_status', 'publish'); $this->db->where('x1.is_deleted', 'false'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } if ($id > 0) $this->db->where('x1.id !=', $id); $i = 0; $this->db->group_start(); foreach ($post_categories as $category) { if ($i == 0) { $this->db->like('x1.post_categories', $category); } else { $this->db->or_like('x1.post_categories', $category); } $i++; } $this->db->group_end(); $this->db->order_by('x1.created_at', 'DESC'); $this->db->limit((__session('post_related_count') > 0 ? __session('post_related_count') : 5)); return $this->db->get(self::$table . ' x1'); } /** * Set Post Counter + 1 * @param Integer $id * @return Boolean */ public function set_post_counter($id) { $this->db->set('post_counter', 'post_counter + 1', FALSE); $this->db->where(self::$pk, $id); return $this->db->update(self::$table); } /** * Search * @param String * @return Resource */ public function search($keyword) { $this->db->select(' x1.id , x1.post_title , x1.created_at , x1.post_content , x1.post_image , x1.post_slug , x1.post_counter , x2.user_full_name AS post_author '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_status', 'publish'); $this->db->where('x1.is_deleted', 'false'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->where_in('x1.post_type', ['post', 'page']); $this->db->group_start(); $this->db->like('LOWER(x1.post_title)', strtolower($keyword)); $this->db->group_end(); $this->db->limit(20); return $this->db->get(self::$table .' x1'); } /** * Get Year From Posted Date * @return Resource */ public function get_years() { $this->db->select('LEFT(created_at, 4) as year'); $this->db->where('post_type', 'post'); $this->db->where('is_deleted', 'false'); $this->db->where('post_status', 'publish'); if ( ! $this->auth->hasLogin() ) { $this->db->where('post_visibility', 'public'); } $this->db->group_by('1'); $this->db->order_by('1', 'DESC'); return $this->db->get(self::$table); } /** * Get Archives * @param Integer $year * @return Resource */ public function get_archives($year) { $this->db->select(" SUBSTR(x1.created_at, 6, 2) AS `code` , MONTHNAME(x1.created_at) AS `month` , COUNT(*) AS `count` "); $this->db->where('LEFT(x1.created_at, 4) = ', _isValidYear($year) ? $year : date('Y')); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.post_status', 'publish'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->where('x1.is_deleted', 'false'); $this->db->group_by("1,2"); $this->db->order_by('1', 'ASC'); return $this->db->get(self::$table . ' x1'); } /** * Get Post by Year and Month * @param String $year * @param String $month * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_post_archives($year, $month, $limit = 0, $offset = 0) { $this->db->select(' x1.id , x1.post_title , x1.created_at , x1.post_content , x1.post_image , x1.post_slug , x1.post_counter , x2.user_full_name AS post_author '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.post_status', 'publish'); $this->db->where('x1.is_deleted', 'false'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->where('LEFT(x1.created_at, 4) = ', _isValidYear($year) ? $year : date('Y')) ; $this->db->where('SUBSTRING(x1.created_at, 6, 2) = ', _isValidMonth($month) ? $month : '01'); $this->db->order_by('x1.created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get Posts by Tags * @param String $tag * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_post_tags($tag = '', $limit = 0, $offset = 0) { $this->db->select(' x1.id , x1.post_title , x1.post_content , x1.created_at , x1.post_image , x1.post_slug , x2.user_full_name AS post_author , x1.post_counter '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.is_deleted', 'false'); $this->db->where('x1.post_status', 'publish'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->group_start(); $this->db->like("LOWER(REPLACE(x1.post_tags, ' ', '-'))", $tag); $this->db->group_end(); $this->db->order_by('x1.created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get Post by category * @param String $category_slug * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_post_categories($category_slug = '', $limit = 0, $offset = 0) { $id = '+0+'; $query = $this->db ->select('id') ->where('category_slug', $category_slug) ->where('category_type', 'post') ->where('is_deleted', 'false') ->limit(1) ->get('categories'); if ($query->num_rows() == 1) { $res = $query->row(); $id = '+' . $res->id . '+'; } $this->db->select(' x1.id , x1.post_title , x1.created_at , x1.post_content , x1.post_image , x1.post_slug , x1.post_counter , x2.user_full_name AS post_author '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'post'); $this->db->where('x1.is_deleted', 'false'); $this->db->where('x1.post_status', 'publish'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->group_start(); $this->db->like('x1.post_categories', $id); $this->db->group_end(); $this->db->order_by('x1.created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get Another Pages * @param Integer $id * @param Integer $limit * @return Resource */ public function get_another_pages( $id = 0, $limit = 0 ) { $this->db->select(' x1.id , x1.post_title , x1.post_content , x1.created_at , x1.post_image , x1.post_slug , x2.user_full_name AS post_author , x1.post_counter '); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'page'); $this->db->where('x1.is_deleted', 'false'); $this->db->where('x1.post_status', 'publish'); if ( ! $this->auth->hasLogin() ) { $this->db->where('x1.post_visibility', 'public'); } $this->db->where('x1.id !=', $id); $this->db->order_by('x1.created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table . ' x1'); } /** * Get Posts for RSS Feed * @return Resource */ public function feed() { $this->db->select('id, post_title, created_at, post_content, post_slug'); $this->db->where('post_type', 'post'); $this->db->where('post_status', 'publish'); $this->db->where('is_deleted', 'false'); if ( ! $this->auth->hasLogin() ) { $this->db->where('post_visibility', 'public'); } $this->db->order_by('created_at', 'DESC'); $this->db->limit((__session('post_rss_count') > 0 ? __session('post_rss_count') : 10)); return $this->db->get(self::$table); } /** * Opening Speech | Kata Sambutan * @return String */ public function get_opening_speech() { $query = $this->db ->select('post_content') ->where('post_type', 'opening_speech') ->limit(1) ->get(self::$table); if ($query->num_rows() === 1) { $result = $query->row(); return $result->post_content; } return ''; } } PKr\sh2//!public/M_class_group_students.phpnu[db->select(" x1.id , x3.identity_number , x3.nisn , x3.full_name , x3.birth_place , x3.birth_date , IF(x3.gender = 'M', 'Laki-laki', 'Perempuan') AS gender , x3.photo "); $this->db->join("class_group_settings x2", "x1.class_group_setting_id = x2.id", "LEFT"); $this->db->join("students x3", "x1.student_id = x3.id", "LEFT"); $this->db->where("x1.is_deleted", "false"); $this->db->where("x2.academic_year_id", (int) $academic_year_id); $this->db->where("x2.class_group_id", (int) $class_group_id); $this->db->order_by("x3.full_name", 'ASC'); return $this->db->get(self::$table . ' x1'); } } PKr\C98public/M_students.phpnu[db->select(" x1.id , x2.identity_number , x2.full_name , IF(x2.gender = 'M', 'L', 'P') AS gender , COALESCE(x2.birth_place, '') birth_place , COALESCE(x2.birth_date, '') AS birth_date , x2.photo "); $this->db->join('students x2', 'x1.student_id = x2.id', 'LEFT'); $this->db->where('x1.is_deleted', 'false'); $this->db->where('x1.academic_year_id', (int) $academic_year_id); $this->db->where('x1.class_group_id', (int) $class_group_id); $this->db->order_by('x2.full_name', 'ASC'); return $this->db->get('class_group_settings x1'); } } PKr\M M_answers.phpnu[db->select('x1.id, x2.question, x1.answer, x1.is_deleted'); $this->db->join('questions x2', 'x1.question_id = x2.id', 'LEFT'); if ( ! empty($keyword) ) { $this->db->like('x2.question', $keyword); $this->db->or_like('x1.answer', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get All Answer By Question ID * @param Integer $question_id * @return Resource */ public function get_answers($question_id) { return $this->db ->select('id, answer') ->where('question_id', _toInteger($question_id)) ->where('is_deleted', 'false') ->get('answers'); } } PKr\dwM_user_students.phpnu[db->select(' x1.id , x1.user_name , x2.full_name AS user_full_name , x2.email AS user_email , x1.is_deleted '); $this->db->join('students x2', 'x1.user_profile_id = x2.id', 'LEFT'); $this->db->where('x1.user_type', 'student'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.user_name', $keyword); $this->db->or_like('x2.full_name', $keyword); $this->db->or_like('x2.email', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } } PKr\{:zM_student_groups.phpnu[db->select(" x1.id , x4.academic_year , CONCAT(x5.class_group, IF((x6.major_short_name <> ''), CONCAT(' ', x6.major_short_name),''), IF((x5.sub_class_group <> ''),CONCAT(' - ', x5.sub_class_group),'')) AS class_name , COALESCE(x2.identity_number, '-') AS identity_number , x2.full_name , x2.birth_place , x2.birth_date , IF(x2.gender = 'M', 'L', 'P') AS gender , x1.is_class_manager , x1.is_deleted "); $this->db->join('students x2', 'x1.student_id = x2.id', 'LEFT'); $this->db->join('class_group_settings x3', 'x1.class_group_setting_id = x3.id', 'LEFT'); $this->db->join('academic_years x4', 'x3.academic_year_id = x4.id', 'LEFT'); $this->db->join('class_groups x5', 'x3.class_group_id = x5.id', 'LEFT'); $this->db->join('majors x6', 'x5.major_id = x6.id', 'LEFT'); $this->db->where('x2.is_student', 'true'); $this->db->where('x2.is_alumni', 'false'); $this->db->where('x2.is_prospective_student', 'false'); if ( ! empty($keyword) ) { $this->db->like('x4.academic_year', $keyword); $this->db->or_like('x2.identity_number', $keyword); $this->db->or_like('x2.full_name', $keyword); $this->db->or_like('x2.birth_place', $keyword); $this->db->or_like('x2.birth_date', $keyword); $this->db->or_like('x2.gender', $keyword); $this->db->or_like("CONCAT(x5.class_group, IF((x6.major_short_name <> ''), CONCAT(' ', x6.major_short_name),''), IF((x5.sub_class_group <> ''), CONCAT(' - ', x5.sub_class_group),''))", $keyword); } $this->db->order_by('x4.academic_year', 'ASC'); $this->db->order_by('x5.class_group', 'ASC'); $this->db->order_by('x5.major_id', 'ASC'); $this->db->order_by('x5.sub_class_group', 'ASC'); $this->db->order_by('x2.full_name', 'ASC'); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Set Class President / Ketua Kelas * @param Integer $id * @param Array $dataset * @return Boolean */ public function set_class_president($id, $dataset) { $class_group_setting_id = 0; $query = $this->model->RowObject('id', $id, 'class_group_students'); if (is_object($query)) { $class_group_setting_id = $query->class_group_setting_id; } if ($class_group_setting_id > 0) { $this->db->trans_start(); if (filter_var((string) $dataset['is_class_manager'], FILTER_VALIDATE_BOOLEAN)) { $this->db ->where('class_group_setting_id', $class_group_setting_id) ->update(self::$table, ['is_class_manager' => 'false']); } $this->db ->where(self::$pk, $id) ->update(self::$table, $dataset); $this->db->trans_complete(); return $this->db->trans_status(); } return FALSE; } } PKr\ZQ Q M_posts.phpnu[db->select(" x1.id , x1.post_title , x2.user_full_name AS post_author , x1.post_status , x1.created_at , x1.is_deleted "); $this->db->join('users x2', 'x1.post_author = x2.id', 'LEFT'); $this->db->where('x1.post_type', 'post'); if (in_array(__session('user_type'), ['student', 'employee'])) { $this->db->where('x1.post_author', __session('user_id')); } if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.post_title', $keyword); $this->db->or_like('x2.user_full_name', $keyword); $this->db->or_like('x1.post_status', $keyword); $this->db->or_like('x1.created_at', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * opening_speech | Sambutan Kepala Sekolah * @return String */ public function get_opening_speech() { $query = $this->db ->select('post_content') ->where('post_type', 'opening_speech') ->limit(1) ->get(self::$table); if ($query->num_rows() === 1) { $result = $query->row(); return $result->post_content; } return ''; } /** * Update Sambutan Kepala Sekolah * @param Array $dataset * @return Boolean */ public function opening_speech_update($dataset = []) { $count = $this->db->where('post_type', 'opening_speech')->count_all_results(self::$table); if ($count === 0) { return $this->db->insert(self::$table, $dataset); } return $this->db->where('post_type', 'opening_speech')->update(self::$table, $dataset); } } PKr\ãiS S M_messages.phpnu[db->select('id, comment_author, comment_email, comment_url, created_at, comment_content, is_deleted'); $this->db->where('comment_type', 'message'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('comment_author', $keyword); $this->db->or_like('comment_email', $keyword); $this->db->or_like('created_at', $keyword); $this->db->or_like('comment_content', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Reply Inbox * @param Integer $id * @param Array $dataset * @return Integer */ public function reply($id, $dataset) { $this->model->update($id, self::$table, $dataset); $query = $this->model->RowObject(self::$pk, $id, self::$table); $sendgrid_api_key = __session('sendgrid_api_key'); $from = new \SendGrid\Email(__session('school_name'), __session('email')); $to = new SendGrid\Email($query->comment_author, $query->comment_email); $content = new SendGrid\Content("text/plain", $dataset['comment_reply']); $mail = new SendGrid\Mail($from, $dataset['comment_subject'], $to, $content); $sendgrid = new \SendGrid($sendgrid_api_key); $response = $sendgrid->client->mail()->send()->post($mail); return $response->statusCode(); } } PKr\6X}gg M_banners.phpnu[db->select('id, link_url, link_title, link_target, link_image, is_deleted'); $this->db->where('link_type', 'banner'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('link_url', $keyword); $this->db->or_like('link_title', $keyword); $this->db->or_like('link_target', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get All Banners * @param Integer $limit * @return Resource */ public function get_banners($limit = 0) { $this->db->select("id, link_title, link_url, link_target, link_image"); $this->db->where('link_type', 'banner'); $this->db->where('is_deleted', 'false'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table); } } PKr\G G M_settings.phpnu[db->select('id, setting_variable, COALESCE(`setting_value`, `setting_default_value`) AS setting_value, setting_description, is_deleted'); $this->db->where('setting_group', $setting_group); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('setting_description', $keyword); $this->db->or_like('setting_value', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get Setting Values * @param Array $access_group * @return Array */ public function get_setting_values($access_group = 'public') { $this->db->select('setting_variable, COALESCE(setting_value, setting_default_value) AS setting_value'); if ($access_group == 'public') $this->db->where('setting_access_group', 'public'); $query = $this->db->get(self::$table); $settings = []; foreach($query->result() as $row) { $settings[$row->setting_variable] = $row->setting_value; } return $settings; } } PKr\p # #M_registrants.phpnu[admission_year = (NULL !== $year && $year > 0) ? $year : date('Y'); } /** * Display a listing of the resource. * @param String $keyword * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_where($keyword = '', $return_type = 'count', $limit = 0, $offset = 0) { $fields = [ "x1.id" , "x1.registration_number" , "x1.re_registration" , "x1.created_at" , "x1.full_name" , "x1.birth_date" , "IF(x1.gender = 'M', 'L', 'P') AS gender" , "x1.photo" , "x1.is_deleted" ]; if (__session('major_count') > 0) { array_push($fields, 'x2.major_name AS first_choice'); array_push($fields, 'x3.major_name AS second_choice'); } $this->db->select(implode(', ', $fields)); if (__session('major_count') > 0) { $this->db->join('majors x2', 'x1.first_choice_id = x2.id', 'LEFT'); $this->db->join('majors x3', 'x1.second_choice_id = x3.id', 'LEFT'); } $this->db->where('x1.is_prospective_student', 'true'); $this->db->where('LEFT(x1.registration_number, 4) = ', $this->admission_year); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.registration_number', $keyword); $this->db->or_like('x1.re_registration', $keyword); $this->db->or_like('x1.created_at', $keyword); if (__session('major_count') > 0) { $this->db->or_like('x2.major_name', $keyword); $this->db->or_like('x3.major_name', $keyword); } $this->db->or_like('x1.full_name', $keyword); $this->db->or_like('x1.gender', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * insert * @param Int $selection_result * @param Array $registration_number * @return Boolean */ public function insert($selection_result, array $registration_number = []) { $approved = 0; $unapproved = 0; $error = 0; foreach($registration_number as $reg_number) { if ($selection_result != 'unapproved') { if ($this->check_quota($reg_number)) { $query = $this->db ->where('registration_number', $reg_number) ->update(self::$table, ['selection_result' => $selection_result]); $query ? $approved++ : $error++; } else { $unapproved++; } } else { $query = $this->db ->where('registration_number', $reg_number) ->update(self::$table, ['selection_result' => $selection_result]); $query ? $approved++ : $error++; } } $response = 'Sukses : '.$approved. ' SQL Error : '. $error.', Gagal : ' . $unapproved; return $response; } /** * check_quota * @access private * @param String * @return Boolean */ private function check_quota($registration_number) { // Get First Choice if (__session('major_count') > 0) { $student = $this->db ->select('first_choice_id') ->where('registration_number', $registration_number) ->get(self::$table) ->row(); } // Set Default Quota $quota = 0; // Get Quota $this->db->select('quota'); $this->db->where('year', $this->admission_year); // If SMK or PT if (__session('major_count') > 0) { $this->db->where('major_id', $student->first_choice_id); } $this->db->limit(1); $query = $this->db->get('admission_quotas'); if ($query->num_rows() === 1) { $result = $query->row(); $quota = $result->quota; } // Get Approved Students $approved = $this->db ->where('is_prospective_student', 'true') ->where('selection_result IS NOT NULL') ->where('selection_result !=', 'unapproved') ->where('LEFT(registration_number, 4) = ', $this->admission_year) ->count_all_results(self::$table); return $quota > $approved; } /** * Generate Registration Number * @return Boolean */ public function registration_number() { $admission_year = $this->admission_year; $query = $this->db->query(" SELECT MAX(RIGHT(registration_number, 6)) AS max_number FROM students WHERE is_prospective_student='true' AND LEFT(registration_number, 4) = ? ", [$admission_year]); $registration_number = "000001"; if ($query->num_rows() === 1) { $data = $query->row(); $number = ((int) $data->max_number) + 1; $registration_number = sprintf("%06s", $number); } return $admission_year . $registration_number; } /** * Selection Result * @param String $registration_number * @param String $birth_date * @return Array */ public function selection_result($registration_number, $birth_date) { $query = $this->db ->where('registration_number', $registration_number) ->where('birth_date', $birth_date) ->get(self::$table); if ($query->num_rows() === 1) { $result = $query->row(); if (is_null($result->selection_result)) { $response['status'] = 'info'; $response['message'] = 'Proses seleksi belum dimulai'; } if ($result->selection_result === 'unapproved') { $response['status'] = 'warning'; $response['message'] = 'Anda Tidak Lolos Seleksi Penerimaan Peserta Didik Baru '.__session('school_name'); } else { $response['status'] = 'success'; if (__session('major_count') > 0) { $majors = $this->model->RowObject('id', $result->selection_result, 'majors'); $response['message'] = 'Anda Lolos Seleksi Penerimaan Peserta Didik Baru dan diterima di ' . __session('_major') . ' ' . $majors->major_name . ' ' . __session('school_name'); } else { $response['message'] = 'Anda Lolos Seleksi Penerimaan Peserta Didik Baru '.__session('school_name'); } } } else { $response['status'] = 'warning'; $response['message'] = 'Data Anda tidak terdaftar pada database kami'; } return $response; } /** * Find Registrant * @param String $registration_number * @param String $birth_date * @return Array */ public function find_registrant($registration_number, $birth_date) { $this->db->select(" x1.id , IF(x1.is_transfer='true', 'Pindahan', 'Baru') AS is_transfer , x1.registration_number , x1.created_at , x2.major_name AS first_choice , x3.major_name AS second_choice , x1.prev_school_name , x1.prev_school_address , x1.full_name , IF(x1.gender = 'M', 'Laki-laki', 'Perempuan') AS gender , x1.nisn , x1.nik , x1.birth_place , x1.birth_date , x4.option_name AS religion , x5.option_name AS special_needs , x6.option_name AS admission_type , x1.street_address , x1.rt , x1.rw , x1.sub_district , x1.district , x1.sub_village , x1.village , x1.postal_code , x1.email "); $this->db->join('majors x2', 'x1.first_choice_id = x2.id', 'LEFT'); $this->db->join('majors x3', 'x1.second_choice_id = x3.id', 'LEFT'); $this->db->join('options x4', 'x1.religion_id = x4.id', 'LEFT'); $this->db->join('options x5', 'x1.special_need_id = x5.id', 'LEFT'); $this->db->join('options x6', 'x1.admission_type_id = x6.id', 'LEFT'); $this->db->where('x1.registration_number', $registration_number); $this->db->where('x1.birth_date', $birth_date); return $this->db->get(self::$table.' x1')->row_array(); } /** * Is Valid Registrant * @param String $registration_number * @param String $birth_date * @return Boolean */ public function is_valid_registrant($registration_number, $birth_date) { $this->db->where('registration_number', $registration_number); $this->db->where('birth_date', $birth_date); $count = $this->db->count_all_results(self::$table); return $count > 0; } /** * Admission Reports * @return Resource */ public function admission_reports() { $this->load->model('m_students'); $query = $this->m_students->student_query(); $query .= " AND x1.is_prospective_student='true' ORDER BY x1.registration_number, x1.full_name ASC"; return $this->db->query($query); } } PKr\3b  M_themes.phpnu[db->select('id, theme_name, theme_folder, theme_author, is_active, is_deleted'); if ( ! empty($keyword) ) { $this->db->like('theme_name', $keyword); $this->db->or_like('theme_folder', $keyword); $this->db->or_like('theme_author', $keyword); } $this->db->order_by('theme_name'); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * get_active_themes * @return String */ public function get_active_themes() { $query = $this->db ->select('theme_folder') ->where('is_active', 'true') ->limit(1) ->get(self::$table); if ($query->num_rows() === 1) { $result = $query->row(); return $result->theme_folder; } return 'magazine'; } /** * Deactivate Themes * @param Integer $id * @return Boolean */ public function deactivate_themes($id = 0) { if ($id > 0) $this->db->where(self::$pk . ' !=', $id); return $this->db->update(self::$table, ['is_active' => 'false']); } } PKr\72Y Y M_post_categories.phpnu[db->select('id, category_name, category_description, category_slug, is_deleted'); $this->db->where('category_type', 'post'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('category_name', $keyword); $this->db->or_like('category_description', $keyword); $this->db->or_like('category_slug', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Dropdown * @return Array */ public function dropdown() { $this->db->select('id, category_name'); $this->db->where('category_type', 'post'); $this->db->order_by('category_name', 'ASC'); $query = $this->db->get(self::$table); $dataset = []; foreach($query->result() as $row) { $dataset[$row->id] = $row->category_name; } return $dataset; } /** * custom Save * @param Array * @return Integer */ public function save($dataset) { $query = $this->db->insert(self::$table, $dataset); return $query ? $this->db->insert_id() : 0; } } PKr\'f  M_dashboard.phpnu[db->query(" SELECT (SELECT COUNT(*) FROM comments x1 WHERE x1.comment_type='message') AS messages , (SELECT COUNT(*) FROM comments x1 WHERE x1.comment_type='post') AS comments , (SELECT COUNT(*) FROM posts x1 WHERE x1.post_type='post') AS posts , (SELECT COUNT(*) FROM posts x1 WHERE x1.post_type='page') AS pages , (SELECT COUNT(*) FROM categories WHERE category_type='post') AS categories , (SELECT COUNT(*) FROM tags) AS tags , (SELECT COUNT(*) FROM links WHERE link_type = 'link') AS links , (SELECT COUNT(*) FROM quotes) AS quotes "); return $query->row(); } } PKr\漠 M_albums.phpnu[db->select('id, album_title, album_description, album_cover, album_slug, is_deleted'); if ( ! empty($keyword) ) { $this->db->like('album_title', $keyword); $this->db->or_like('album_description', $keyword); $this->db->or_like('album_slug', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get Albums * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_albums($limit = 0, $offset = 0) { $this->db->select(" id , album_title , album_description , COALESCE(album_cover, 'no-image.png') AS album_cover , album_slug "); $this->db->where('is_deleted', 'false'); $this->db->order_by('created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } } PKr\4  M_quotes.phpnu[db->select('id, quote, quote_by, is_deleted'); if ( ! empty($keyword) ) { $this->db->like('quote', $keyword); $this->db->or_like('quote_by', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get All Quotes * @param Integer $limit * @return Resource */ public function get_quotes($limit = 0) { $this->db->select('id, quote, quote_by'); $this->db->where('is_deleted', 'false'); $this->db->order_by('created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table); } } PKr\8CM_class_group_students.phpnu[db->select(" x1.id , x2.academic_year , CONCAT(x3.class_group, IF((x4.major_short_name <> ''), CONCAT(' ',x4.major_short_name),''),IF((x3.sub_class_group <> ''),CONCAT(' - ',x3.sub_class_group),'')) AS class_group , COALESCE(x5.identity_number, '') AS identity_number , COALESCE(x5.nisn, '') AS nisn , x5.full_name , x5.gender , COALESCE(x5.birth_place, '') AS birth_place , COALESCE(x5.birth_date, '') AS birth_date , x1.is_deleted "); $this->db->join('academic_years x2', 'x1.academic_year_id = x2.id', 'LEFT'); $this->db->join('class_groups x3', 'x1.class_group_id = x3.id', 'LEFT'); $this->db->join('majors x4', 'x3.major_id = x4.id', 'LEFT'); $this->db->join('students x5', 'x1.student_id = x5.id', 'LEFT'); $this->db->where('x5.is_student', 'true'); $this->db->where('x5.is_alumni', 'false'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x2.academic_year', $keyword); $this->db->or_like("CONCAT(x3.class_group, IF((x4.major_short_name <> ''), CONCAT(' ',x4.major_short_name),''),IF((x3.sub_class_group <> ''),CONCAT(' - ',x3.sub_class_group),''))", $keyword); $this->db->or_like('x5.identity_number', $keyword); $this->db->or_like('x5.nisn', $keyword); $this->db->or_like('x5.full_name', $keyword); $this->db->or_like('x5.gender', $keyword); $this->db->or_like('x5.birth_place', $keyword); $this->db->or_like('x5.birth_date', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get Students * @param Integer $academic_year_id * @param Integer $class_group_id * @return Resource */ public function get_students($academic_year_id, $class_group_id) { // Get "Aktif" Student Status ID $student_status_id = get_option_id('student_status', 'aktif'); if ($class_group_id == 'unset') { $student_ids = $this->db ->select('student_id') ->from('class_group_students') ->group_by('student_id') ->get_compiled_select(); $query = $this->db ->select('id, identity_number, full_name') ->where('id NOT IN(' . $student_ids . ')') ->where('is_student', 'true') ->where('is_alumni', 'false') ->where('student_status_id', _toInteger($student_status_id)) ->get('students'); } else if ($class_group_id == 'show_all') { $query = $this->db ->select('id, identity_number, full_name') ->where('is_student', 'true') ->where('is_alumni', 'false') ->where('student_status_id', _toInteger($student_status_id)) ->get('students'); } else { $class_group_setting = $this->db ->select('id') ->where('academic_year_id', $academic_year_id) ->where('class_group_id', $class_group_id) ->get('class_group_settings'); if ($class_group_setting->num_rows() === 1) { $res = $class_group_setting->row(); $class_group_setting_id = $res->id; $query = $this->db ->select('x2.id, x2.identity_number, x2.full_name') ->join('students x2', 'x1.student_id = x2.id', 'LEFT') ->where('x1.class_group_setting_id', $class_group_setting_id) ->where('x1.is_deleted', 'false') ->where('x2.is_deleted', 'false') ->where('x2.is_alumni', 'false') ->where('x2.is_student', 'true') ->get(self::$table.' x1'); } } $dataset = []; if (isset($query) && is_object($query)) { foreach($query->result() as $row) { $dataset[] = [ 'id' => $row->id, 'identity_number' => $row->identity_number, 'full_name' => $row->full_name ]; } } return $dataset; } /** * Save to Destination Class * @param Integer $ids * @param Integer $academic_year_id * @param Integer $class_group_id * @return Boolean */ public function save_to_destination_class($ids, $academic_year_id, $class_group_id) { // Get Active student Status ID $student_status_id = get_option_id('student_status', 'aktif'); // Get Class Group Setting $class_group_setting_id = 0; $query = $this->db ->select('id') ->where('academic_year_id', $academic_year_id) ->where('class_group_id', $class_group_id) ->get('class_group_settings'); if ($query->num_rows() === 1) { $res = $query->row(); $class_group_setting_id = $res->id; } $success = 0; if ($class_group_setting_id > 0) { foreach ($ids as $id) { $dataset = [ 'student_id' => $id, 'class_group_setting_id' => $class_group_setting_id, 'created_at' => date('Y-m-d H:i:s'), 'created_by' => (int) __session('user_id') ]; if ($this->db->insert(self::$table, $dataset)) { // if Success, update student status to "Aktif" $this->db->where('id', $id)->update('students', ['student_status_id' => $student_status_id]); $success++; } } } return $success > 0; } /** * Delete Permanently * @param Array $ids * @param Integer $academic_year_id * @param Integer $class_group_ide * @return Boolean */ public function delete_permanently($ids, $academic_year_id, $class_group_id) { $class_group_setting_id = 0; $query = $this->db ->select('id') ->where('academic_year_id', $academic_year_id) ->where('class_group_id', $class_group_id) ->get('class_group_settings'); if ($query->num_rows() === 1) { $res = $query->row(); $class_group_setting_id = $res->id; } return $this->db ->where('class_group_setting_id', $class_group_setting_id) ->where_in('student_id', $ids) ->delete(self::$table); } } PKr\00M_questions.phpnu[db->select('id, question, is_active, is_deleted'); if ( ! empty($keyword) ) $this->db->like('question', $keyword); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get Dropdown * @return Array */ public function dropdown() { $this->db->select('id, question'); $query = $this->db->get(self::$table); $dataset = []; foreach($query->result() as $row) { $dataset[$row->id] = $row->question; } return $dataset; } /** * Get Active Question * @return Resource */ public function get_active_question() { return $this->db ->select('id, question') ->where('is_active', 'true') ->where('is_deleted', 'false') ->limit(1) ->get(self::$table) ->row(); } } PKr\( index.htmlnu[ 403 Forbidden

Directory access is forbidden.

PKr\jYk k M_files.phpnu[db->select(' x1.id , x1.file_title , x1.file_name , x1.file_ext , x1.file_size , x2.category_name , x1.file_counter , x1.file_visibility , x1.is_deleted '); $this->db->join('categories x2', 'x1.file_category_id = x2.id', 'LEFT'); $this->db->where('x2.category_type', 'file'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.file_title', $keyword); $this->db->or_like('x1.file_name', $keyword); $this->db->or_like('x1.file_ext', $keyword); $this->db->or_like('x1.file_size', $keyword); $this->db->or_like('x2.category_name', $keyword); $this->db->or_like('x1.file_visibility', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get Files * @param String $slug * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_files($slug = '', $limit = 0, $offset = 0) { $this->db->select(' x1.id , x1.file_title , x1.file_name , x1.file_ext , x1.file_size , x2.category_name , x1.file_counter , x1.file_visibility '); $this->db->join("categories x2", "x1.file_category_id = x2.id AND x2.category_type = 'file'", "LEFT"); $this->db->where('x1.is_deleted', 'false'); if (!empty($slug)) $this->db->where('x2.category_slug', $slug); if ( ! $this->auth->hasLogin() ) $this->db->where('x1.file_visibility', 'public'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Set File Counter + 1 * @param Integer $id * @return Void */ public function set_file_counter( $id ) { $this->db->set('file_counter', 'file_counter + 1', FALSE); $this->db->where('id', _toInteger($id)); $this->db->update('files'); } } PKr\eM_pollings.phpnu[db ->where('ip_address', get_ip_address()) ->where('LEFT(created_at, 10)=', date('Y-m-d')) ->count_all_results(self::$table); if ($count === 0) { $this->db->set('answer_id', $answer_id); $this->db->set('ip_address', get_ip_address()); $this->db->set('created_at', date('Y-m-d H:i:s')); $this->db->set('created_by', __session('user_id')); return $this->db->insert(self::$table); } return FALSE; } /** * Polling Result * @param Integer $question_id * @return Resource */ public function get_pollings($question_id) { $this->db->select('x2.answer AS labels, COUNT(*) AS data'); $this->db->join('answers x2', 'x1.answer_id = x2.id', 'LEFT'); $this->db->where('x2.question_id', _toInteger($question_id)); $this->db->group_by('x1.answer_id'); $this->db->order_by('x1.answer_id', 'ASC'); return $this->db->get(self::$table . ' x1'); } } PKr\ M_file_categories.phpnu[db->select(' id , category_name , category_description , category_slug , is_deleted '); $this->db->where('category_type', 'file'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('category_name', $keyword); $this->db->or_like('category_description', $keyword); $this->db->or_like('category_slug', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get all data * @return Resource */ public function get_file_categories() { return $this->db ->select('id, category_name, category_description, category_slug') ->where('category_type', 'file') ->where('is_deleted', 'false') ->get(self::$table); } /** * Dropdown * @return Array */ public function dropdown() { $query = $this->db ->select('id, category_name') ->where('category_type', 'file') ->where('is_deleted', 'false') ->get(self::$table); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = $row->category_name; } } return $dataset; } } PKr\j7A%%M_admission_quotas.phpnu[db->select(" x1.id , x2.academic_year , x3.option_name AS admission_type , COALESCE(x4.major_name, '-') AS major_name , x1.quota , x1.is_deleted "); $this->db->join('academic_years x2', 'x1.academic_year_id = x2.id', 'LEFT'); $this->db->join('options x3', 'x1.admission_type_id = x3.id', 'LEFT'); $this->db->join('majors x4', 'x1.major_id = x4.id', 'LEFT'); if ( ! empty($keyword) ) { $this->db->like('x2.academic_year', $keyword); $this->db->or_like('x3.option_name', $keyword); $this->db->or_like('x4.major_name', $keyword); $this->db->or_like('x1.quota', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } } PKr\{$u u M_registrants_unapproved.phpnu[admission_year = (NULL !== $year && $year > 0) ? $year : date('Y'); } /** * Display a listing of the resource. * @param String $keyword * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_where($keyword = '', $return_type = 'count', $limit = 0, $offset = 0) { $fields = [ 'x1.id' , 'x1.registration_number' , 'x1.re_registration' , 'x1.created_at' , 'x1.full_name' , 'x1.birth_date' , 'x1.gender' ]; if (__session('major_count') > 0) { array_push($fields, 'x2.major_name AS selection_result'); } else { array_push($fields, 'x1.selection_result'); } $this->db->select(implode(', ', $fields)); if (__session('major_count') > 0) { $this->db->join('majors x2', 'x1.selection_result = x2.id', 'LEFT'); } $this->db->where('x1.is_alumni', 'false'); $this->db->where('x1.is_prospective_student', 'true'); $this->db->where('x1.selection_result', 'unapproved'); $this->db->where('LEFT(x1.registration_number, 4) = ', $this->admission_year); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.registration_number', $keyword); if (__session('major_count') > 0) { $this->db->or_like('x2.major_name', $keyword); } else { $this->db->or_like('x1.selection_result', $keyword); } $this->db->or_like('x1.re_registration', $keyword); $this->db->or_like('x1.full_name', $keyword); $this->db->or_like('x1.gender', $keyword); $this->db->or_like('x1.birth_date', $keyword); $this->db->or_like('x1.created_at', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } } PKr\L M_alumni.phpnu[db->select(" id , identity_number , full_name , gender , street_address , photo , is_alumni , COALESCE(start_date, '') start_date , end_date , is_deleted "); $this->db->where_in('is_alumni', ['true', 'false', 'unverified']); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('identity_number', $keyword); $this->db->or_like('full_name', $keyword); $this->db->or_like('gender', $keyword); $this->db->or_like('street_address', $keyword); $this->db->or_like('start_date', $keyword); $this->db->or_like('end_date', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get Alumni * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_alumni($limit = 0, $offset = 0) { $this->db->select(" id , identity_number , full_name , IF(gender = 'M', 'Laki-laki', 'Perempuan') as gender , birth_place , LEFT(start_date, 4) AS start_date , LEFT(end_date, 4) AS end_date , birth_date , photo "); $this->db->where('is_deleted', 'false'); $this->db->where('is_alumni', 'true'); $this->db->order_by('end_date', 'ASC'); $this->db->order_by('full_name', 'ASC'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Alumni Reports * @return Resource */ public function alumni_reports() { $this->load->model('m_students'); $query = $this->m_students->student_query(); $query .= " AND x1.is_alumni='true' ORDER BY x1.full_name ASC"; return $this->db->query($query); } /** * Get Inactive Accounts * @return Resource */ public function get_inactive_accounts() { $this->db->select('x1.id, x1.identity_number, x1.full_name, x1.email'); $this->db->join('users x2', 'x1.id = x2.user_profile_id AND x2.user_type = "student"', 'LEFT'); $this->db->where('x2.user_profile_id', NULL); $this->db->where('x1.is_alumni', 'true'); $this->db->where('x1.is_deleted', 'false'); return $this->db->get('students x1'); } } PKr\| M_achievements.phpnu[db->select('id, achievement_description, achievement_type, achievement_level, achievement_year, achievement_organizer, is_deleted'); if (__session('user_type') === 'student') { $this->db->where('student_id', __session('user_profile_id')); } if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('achievement_description', $keyword); $this->db->or_like('achievement_type', $keyword); $this->db->or_like('achievement_level', $keyword); $this->db->or_like('achievement_year', $keyword); $this->db->or_like('achievement_organizer', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get By Student ID * @param Integer $student_id * @return Resource */ public function get_by_student_id($student_id = 0) { $this->db->select(' id , achievement_description , achievement_type , achievement_level , achievement_year , achievement_organizer , is_deleted '); $this->db->where('student_id', $student_id); $this->db->where('is_deleted', 'false'); return $this->db->get(self::$table); } } PKr\gFRM_user_employees.phpnu[db->select(' x1.id , x1.user_name , x2.full_name AS user_full_name , x2.email AS user_email , x1.is_deleted '); $this->db->join('employees x2', 'x1.user_profile_id = x2.id', 'LEFT'); $this->db->where('x1.user_type', 'employee'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.user_name', $keyword); $this->db->or_like('x2.full_name', $keyword); $this->db->or_like('x2.email', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } } PKr\{d ~~ M_helper.phpnu[db->trans_start(); $this->db->insert($table, $dataset); $this->db->trans_complete(); return $this->db->trans_status(); } /** * Update * @param Integer $id * @param String $table * @param Array $dataset * @return Boolean */ public function update($id, $table, array $dataset) { $this->db->trans_start(); $this->db->where(self::$pk, $id)->update($table, $dataset); $this->db->trans_complete(); return $this->db->trans_status(); } /** * Update Or Insert * @param Integer $id * @param String $table * @param Array $dataset * @return Boolean */ public function upsert($id, $table, array $dataset) { $this->db->trans_start(); _isNaturalNumber( $id ) ? $this->db->where(self::$pk, $id)->update($table, $dataset) : $this->db->insert($table, $dataset); $this->db->trans_complete(); return $this->db->trans_status(); } /** * Delete Permanently * @param String $key * @param String $value * @param String $table * @return Boolean */ public function delete_permanently($key, $value, $table) { $this->db->trans_start(); $this->db->where_in($key, $value)->delete($table); $this->db->trans_complete(); return $this->db->trans_status(); } /** * Delete * @param Array $ids * @param String $table * @return Boolean */ public function delete(array $ids, $table) { $this->db->trans_start(); $this->db->where_in(self::$pk, $ids) ->update($table, [ 'is_deleted' => 'true', 'deleted_by' => __session('user_id'), 'deleted_at' => date('Y-m-d H:i:s') ] ); $this->db->trans_complete(); return $this->db->trans_status(); } /** * Truncate Table * @param String $table * @return Boolean */ public function truncate($table) { $this->db->trans_start(); $this->db->truncate($table); $this->db->trans_complete(); return $this->db->trans_status(); } /** * Restore * @param Array $ids * @param String $table * @return Boolean */ public function restore(array $ids, $table) { $this->db->trans_start(); $this->db->where_in(self::$pk, $ids) ->update($table, [ 'is_deleted' => 'false', 'restored_by' => __session('user_id'), 'restored_at' => date('Y-m-d H:i:s') ] ); $this->db->trans_complete(); return $this->db->trans_status(); } /** * Check value if exists * @param String $key * @param String $value * @param String $table * @return Boolean */ public function is_exists($key, $value, $table) { $count = $this->db ->where($key, $value) ->count_all_results($table); return $count > 0; } /** * Row Object * @param String $key * @param String $value * @param String $table * @return Object */ public function RowObject($key, $value, $table) { return $this->db ->where($key, $value) ->get($table) ->row(); } /** * Results Object * @param String $table * @return Array of Object */ public function ResultsObject($table) { return $this->db->get($table)->result(); } /** * Row Array * @param String $table * @param String $key * @param String $value * @return Array */ public function RowArray($table, $key, $value) { return $this->db ->where($key, $value) ->get($table) ->row_array(); } /** * Results Array * @param String $table * @return Array of Array */ public function ResultsArray($table) { return $this->db->get($table)->result_array(); } /** * Check if NIK exists * @param String $nik * @param String $table * @param Integer $id * @return Boolean */ public function nik_exists($nik, $table = '', $id = 0) { // Students $this->db->where('nik', $nik); if ( $table == 'students' && _isNaturalNumber($id) ) $this->db->where('id !=', _toInteger($id)); $this->db->where('is_deleted', 'false'); $student = $this->db->count_all_results('students'); // Employees $this->db->where('nik', $nik); if ( $table == 'employees' && _isNaturalNumber($id) ) $this->db->where('id !=', _toInteger($id)); $this->db->where('is_deleted', 'false'); $employee = $this->db->count_all_results('employees'); if ($student > 0 || $employee > 0) return true; return false; } /** * Clear Expired Session and Login Attemps * @return Void */ public function clear_expired_session() { $this->db->query("DELETE FROM `_sessions` WHERE DATE_FORMAT(FROM_UNIXTIME(timestamp), '%Y-%m-%d') < CURRENT_DATE"); $this->db->query("DELETE FROM `login_attempts` WHERE DATE_FORMAT(created_at, '%Y-%m-%d') < CURRENT_DATE"); } /** * Get Admission Year * @param Integer $admission_year_id * @return Integer */ public function get_admission_year($admission_year_id = 0) { $admission_year = date('Y'); $query = $this->db ->select('academic_year') ->where('id', $admission_year_id) ->get('academic_years'); if ($query->num_rows() === 1) { $res = $query->row(); $admission_year = substr($res->academic_year, 0, 4); } return $admission_year; } } PKr\ M_photos.phpnu[db->select('x1.id, CONCAT("thumbnail/",x1.photo_name) AS photo_name, x2.album_title, x1.is_deleted'); $this->db->join('albums x2', 'x1.photo_album_id=x2.id', 'left'); if ( ! empty($keyword) ) $this->db->like('x2.album_title', $keyword); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Delete Permanently * @param Integer $id * @return Boolean */ public function delete_permanently($id) { $this->db->trans_start(); $this->db->where(self::$pk, $id)->delete(self::$table); $this->db->trans_complete(); return $this->db->trans_status(); } /** * Get Photos By ALbum ID * @param Integer $id * @return Resource */ public function get_photos($id) { return $this->db ->select('photo_name') ->where('photo_album_id', $id) ->get(self::$table); } } PKr\o*{M_categories.phpnu[db->select('id, category_name, category_description, category_slug'); $this->db->where('category_type', $category_type); $this->db->where('is_deleted', 'false'); $this->db->order_by('category_name', 'ASC'); if ($limit > 0) $this->db->limit($limit); return $this->db->get(self::$table); } } PKr\N))M_students.phpnu[db->select(" x1.id , COALESCE(x1.identity_number, '') identity_number , x1.full_name , x2.option_name AS student_status , x1.gender , COALESCE(x1.birth_place, '') birth_place , x1.birth_date , x1.photo , x1.is_deleted "); $this->db->join('options x2', 'x1.student_status_id = x2.id', 'LEFT'); $this->db->where('x1.is_student', 'true'); $this->db->where('x1.is_alumni', 'false'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.identity_number', $keyword); $this->db->or_like('x1.full_name', $keyword); $this->db->or_like('x2.option_name', $keyword); $this->db->or_like('x1.gender', $keyword); $this->db->or_like('x1.birth_place', $keyword); $this->db->or_like('x1.birth_date', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Chart by Student Status * @param Integer $academic_year_id * @return Array */ public function chart_by_student_status($academic_year_id) { // Sub Query $this->db->select('x1.student_id'); $this->db->join('class_group_settings x2', 'x1.class_group_setting_id = x2.id', 'LEFT'); $this->db->where('x2.academic_year_id', _toInteger($academic_year_id)); $this->db->group_by('x1.student_id'); $student_ids = $this->db->get_compiled_select('class_group_students x1'); // Query $this->db->select('x2.option_name AS labels, COUNT(*) AS data'); $this->db->join('options x2', 'ON x1.student_status_id = x2.id', 'LEFT'); $this->db->where('x1.is_student', 'true'); $this->db->where('x1.is_student', 'true'); $this->db->where('x1.is_alumni', 'false'); $this->db->where('x1.id IN (' . $student_ids . ')'); $this->db->group_by('x2.option_name'); $this->db->order_by('x2.option_name', 'ASC'); return $this->db->get('students x1'); } /** * Chart by Class Group * @param Integer $academic_year_id * @return Array */ public function chart_by_class_groups($academic_year_id) { return $this->db->query(" SELECT CONCAT(x3.class_group, IF((x4.major_short_name <> ''), CONCAT(' ', x4.major_short_name),''),IF((x3.sub_class_group <> ''),CONCAT(' - ',x3.sub_class_group),'')) AS labels , COUNT(*) AS data FROM class_group_students x1 LEFT JOIN class_group_settings x2 ON x1.class_group_setting_id = x2.id LEFT JOIN class_groups x3 ON x2.class_group_id = x3.id LEFT JOIN majors x4 ON x3.major_id = x4.id WHERE x2.academic_year_id = ? GROUP BY 1 ", [_toInteger($academic_year_id)]); } /** * Chart by End Date * @return Array */ public function chart_by_end_date() { return $this->db->query(" SELECT LEFT(x1.end_date, 4) AS labels , COUNT(*) AS data FROM students x1 WHERE x1.is_alumni='true' AND x1.is_deleted='false' GROUP BY 1 ORDER BY 1 ASC "); } /** * Update student to Alumni * @param Array $ids * @param String $end_date * @return Boolean */ public function set_as_alumni($ids, $end_date) { $student_status_id = get_option_id('student_status', 'lulus'); $dataset = []; $dataset['is_alumni'] = 'true'; $dataset['end_date'] = $end_date.'-05-01'; if ($student_status_id > 0) { $dataset['student_status_id'] = $student_status_id; } return $this->db ->where_in('id', $ids) ->update(self::$table, $dataset); } /** * Student Reports * @return Resource */ public function student_reports() { $query = $this->student_query(); $query .= " AND x1.is_student='true' AND x1.is_alumni='false' ORDER BY x1.identity_number, x1.full_name ASC"; return $this->db->query($query); } /** * Student Query * @return String */ public function student_query() { return " SELECT x1.id , x2.major_name , x3.major_name AS first_choice , x4.major_name AS second_choice , x1.registration_number , x1.created_at , x1.admission_exam_number , x1.prev_exam_number , CASE WHEN x1.selection_result IS NULL THEN 'Belum Diseleksi' WHEN x1.selection_result = 'approved' THEN 'Diterima' WHEN x1.selection_result = 'unapproved' THEN 'Tidak Diterima' WHEN x1.selection_result > 0 THEN (SELECT major_name FROM majors WHERE id = x1.selection_result) ELSE '-' END AS selection_result , x5.phase_name , x6.option_name AS admission_type , x1.photo , IF(x1.is_transfer = 'true', 'Pindahan', 'Baru') AS is_transfer , x1.achievement , IF(x1.re_registration = 'true', 'Ya', 'Tidak') AS re_registration , x1.start_date , x1.identity_number , x1.nisn , x1.nik , x1.prev_diploma_number , IF(x1.paud = 'true', 'Ya', 'Tidak') AS paud , IF(x1.tk = 'true', 'Ya', 'Tidak') AS tk , x1.skhun , x1.prev_school_name , x1.prev_school_address , x1.hobby , x1.ambition , x1.full_name , IF(x1.gender = 'M', 'Laki-laki', 'Perempuan') AS gender , x1.birth_place , x1.birth_date , x7.option_name AS religion , x8.option_name AS special_need , x1.street_address , x1.rt , x1.rw , x1.sub_village , x1.village , x1.sub_district , x1.district , x1.postal_code , x9.option_name AS residence , x10.option_name AS transportation , x1.phone , x1.mobile_phone , x1.email , x1.sktm , x1.kks , x1.kps , x1.kip , x1.kis , x1.citizenship , x1.country , x1.father_name , x1.father_birth_year , x11.option_name AS father_education , x12.option_name AS father_employment , x13.option_name AS father_monthly_income , x14.option_name AS father_special_need , x1.mother_name , x1.mother_birth_year , x15.option_name AS mother_education , x16.option_name AS mother_employment , x17.option_name AS mother_monthly_income , x18.option_name AS mother_special_need , x1.guardian_name , x1.guardian_birth_year , x19.option_name AS guardian_education , x20.option_name AS guardian_employment , x21.option_name AS guardian_monthly_income , x1.mileage , x1.traveling_time , x1.height , x1.weight , x1.sibling_number , x22.option_name AS student_status , x1.end_date , x1.reason FROM students x1 LEFT JOIN majors x2 ON x1.major_id = x2.id LEFT JOIN majors x3 ON x1.first_choice_id = x3.id LEFT JOIN majors x4 ON x1.second_choice_id = x4.id LEFT JOIN admission_phases x5 ON x1.admission_phase_id = x5.id LEFT JOIN options x6 ON x1.admission_type_id = x6.id LEFT JOIN options x7 ON x1.religion_id = x7.id LEFT JOIN options x8 ON x1.special_need_id = x8.id LEFT JOIN options x9 ON x1.residence_id = x9.id LEFT JOIN options x10 ON x1.transportation_id = x10.id LEFT JOIN options x11 ON x1.father_education_id = x11.id LEFT JOIN options x12 ON x1.father_employment_id = x12.id LEFT JOIN options x13 ON x1.father_monthly_income_id = x13.id LEFT JOIN options x14 ON x1.father_special_need_id = x14.id LEFT JOIN options x15 ON x1.mother_education_id = x15.id LEFT JOIN options x16 ON x1.mother_employment_id = x16.id LEFT JOIN options x17 ON x1.mother_monthly_income_id = x17.id LEFT JOIN options x18 ON x1.mother_special_need_id = x18.id LEFT JOIN options x19 ON x1.guardian_education_id = x19.id LEFT JOIN options x20 ON x1.guardian_employment_id = x20.id LEFT JOIN options x21 ON x1.guardian_monthly_income_id = x21.id LEFT JOIN options x22 ON x1.student_status_id = x22.id WHERE 1=1 "; } /** * Get Inactive Accounts * @return Resource */ public function get_inactive_accounts() { $this->db->select('x1.id, x1.identity_number, x1.full_name, x1.email'); $this->db->join('users x2', 'x1.id = x2.user_profile_id AND x2.user_type = "student"', 'LEFT'); $this->db->where('x2.user_profile_id', NULL); $this->db->where('x1.is_student', 'true'); $this->db->where('x1.is_deleted', 'false'); return $this->db->get('students x1'); } /** * Student Profile * @param Integer $id * @return Resource */ public function profile($id) { $query = $this->student_query(); $query .= ' AND x1.id = ? '; return $this->db->query($query, [_toInteger($id)])->row(); } /** * Identity Number Exists ? * @param Integer $identity_number * @param Integer $id * @return Boolean */ public function identity_number_exists($identity_number, $id = 0) { $this->db->where('identity_number', $identity_number); if ( _isNaturalNumber($id) ) $this->db->where('id <>', _toInteger($id)); $this->db->where('is_deleted', 'false'); $count = $this->db->count_all_results(self::$table); return $count > 0; } /** * Check if nik exists * @param String $nik * @param Integer $id * @return Boolean */ public function nik_exists( $nik, $id = 0 ) { $this->db->where('nik', $nik); if ( _isNaturalNumber($id) ) $this->db->where('id <>', _toInteger($id)); $this->db->where('is_deleted', 'false'); $count = $this->db->count_all_results(self::$table); return $count > 0; } /** * Check if email exists * @param String $email * @param Integer $id * @return Boolean */ public function email_exists( $email, $id = 0 ) { $this->db->where('email', $email); if ( _isNaturalNumber($id) ) $this->db->where('id <>', _toInteger($id)); $this->db->where('is_deleted', 'false'); $count = $this->db->count_all_results(self::$table); return $count > 0; } } PKr\ M_registrants_approved.phpnu[admission_year = (NULL !== $year && $year > 0) ? $year : date('Y'); } /** * Display a listing of the resource. * @param String $keyword * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_where($keyword = '', $return_type = 'count', $limit = 0, $offset = 0) { $fields = [ 'x1.id' , 'x1.registration_number' , 'x1.re_registration' , 'x1.created_at' , 'x1.full_name' , 'x1.birth_date' , 'x1.gender' ]; if (__session('major_count') > 0) { array_push($fields, 'x2.major_name AS selection_result'); } else { array_push($fields, "IF(x1.selection_result = 'approved','Diterima','Tidak Diterima') AS selection_result"); } $this->db->select(implode(', ', $fields)); if (__session('major_count') > 0) { $this->db->join('majors x2', 'x1.selection_result = x2.id', 'LEFT'); } $this->db->where('x1.is_alumni', 'false'); $this->db->where('x1.is_prospective_student', 'true'); $this->db->where('x1.selection_result IS NOT NULL'); $this->db->where('x1.selection_result !=', 'unapproved'); $this->db->where('LEFT(x1.registration_number, 4) = ', $this->admission_year); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.registration_number', $keyword); if (__session('major_count') > 0) { $this->db->or_like('x2.major_name', $keyword); } else { $this->db->or_like('x1.selection_result', $keyword); } $this->db->or_like('x1.re_registration', $keyword); $this->db->or_like('x1.full_name', $keyword); $this->db->or_like('x1.gender', $keyword); $this->db->or_like('x1.birth_date', $keyword); $this->db->or_like('x1.created_at', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } } PKr\w M_post_comments.phpnu[db->select(' x1.id , x1.comment_author , x1.comment_email , x1.comment_url , x1.created_at , x1.comment_content , x1.comment_reply , x1.comment_status , x2.post_title , x2.id AS comment_post_id , x2.post_slug , x1.is_deleted' ); $this->db->join('posts x2', 'x1.comment_post_id = x2.id', 'LEFT'); $this->db->where('x1.comment_type', 'post'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.comment_author', $keyword); $this->db->or_like('x1.comment_email', $keyword); $this->db->or_like('x1.comment_url', $keyword); $this->db->or_like('x2.post_title', $keyword); $this->db->or_like('x1.created_at', $keyword); $this->db->or_like('x1.comment_content', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Get Recent Comments * @param Integer $limit * @return Resource */ public function get_recent_comments($limit = 0) { $this->db->select(' x2.id , x1.comment_author , x1.comment_url , x1.comment_content , x1.comment_reply , x2.id AS comment_post_id , x2.post_title , x2.post_slug , x1.created_at '); $this->db->join('posts x2', 'x1.comment_post_id = x2.id', 'LEFT'); $this->db->where('x1.comment_type', 'post'); $this->db->where('x1.comment_status', 'approved'); $this->db->where('x1.is_deleted', 'false'); $this->db->order_by('x1.created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit); return $this->db->get(self::$table. ' x1'); } /** * Get more comments * @param Integer $comment_post_id * @param Integer $limit * @param Integer $offset * @return Resource */ public function get_post_comments($comment_post_id = 0, $limit = 0, $offset = 0) { $this->db->select(' x1.id , x1.comment_author , x1.comment_url , x1.created_at , x1.comment_content , x1.comment_reply '); $this->db->join('posts x2', 'x1.comment_post_id = x2.id', 'LEFT'); $this->db->where('x1.comment_type', 'post'); $this->db->where('x1.comment_status', 'approved'); $this->db->where('x1.is_deleted', 'false'); $this->db->where('x1.comment_post_id', $comment_post_id); $this->db->order_by('x1.created_at', 'DESC'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } } PKr\u u M_options.phpnu[db->select('id, option_group, option_name, is_deleted'); $this->db->where('option_group', $option_group); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('option_name', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get Options * @param String $keyword * @return Array */ public function get_options($option_group = 'student_status') { $query = $this->db ->select('id, option_name') ->where('option_group', $option_group) ->where('is_deleted', 'false') ->order_by('option_name', 'ASC') ->get(self::$table); $dataset = []; foreach($query->result() as $row) { $dataset[$row->id] = $row->option_name; } return $dataset; } /** * Get option ID * @param String $option_group * @param String $option_name * @return Integer */ public function get_option_id($option_group = '', $option_name = '') { $this->db->select('id'); $this->db->where('option_group', $option_group); $this->db->where('LOWER(option_name)', trim(strtolower($option_name))); $this->db->limit(1); $query = $this->db->get('options'); if ($query->num_rows() === 1) { $res = $query->row(); return $res->id; } return 0; } } PKr\  M_modules.phpnu[db->select('id, module_name, module_description, module_url, is_deleted'); if ( ! empty($keyword) ) { $this->db->like('module_name', $keyword); $this->db->or_like('module_description', $keyword); $this->db->or_like('module_url', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Dropdown * @return Array */ public function dropdown() { $query = $this->db ->select('id, module_name') ->where('is_deleted', 'false') ->get(self::$table); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = $row->module_name; } } return $dataset; } } PKr\]. M_tags.phpnu[db->select('id, tag, slug, is_deleted'); if ( ! empty($keyword) ) { $this->db->like('tag', $keyword); $this->db->or_like('slug', $keyword); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Get All Tags * @param Integer $limit * @param Boolean $random * @return Resource */ public function get_tags($limit = 0, $random = FALSE) { $this->db->select('id, tag, slug'); $this->db->where('is_deleted', 'false'); if ( $limit > 0 ) $this->db->limit($limit); if ($random) $this->db->order_by('id','RANDOM'); return $this->db->get(self::$table); } /** * Create Tag from posts * @param String $post_tags * @return Void */ public function insert($post_tags) { $tags = explode(',', $post_tags); foreach ($tags as $tag) { $this->db->set('tag', trim($tag)); $this->db->set('slug', slugify(trim($tag))); $this->db->set('created_at', date('Y-m-d H:i:s')); $this->db->set('created_by', __session('user_id')); $query = $this->db->get_compiled_insert(self::$table); $query = str_replace('INSERT INTO', 'INSERT IGNORE INTO', $query); $this->db->query($query); } } } PKr\k M_user_administrator.phpnu[db->select(' x1.id , x1.user_name , x1.user_full_name , x1.user_email , x1.user_url , x2.user_group , x1.is_deleted '); $this->db->join('user_groups x2', 'x1.user_group_id = x2.id', 'LEFT'); $this->db->where('x1.user_type', 'administrator'); if ( ! empty($keyword) ) { $this->db->group_start(); $this->db->like('x1.user_name', $keyword); $this->db->or_like('x1.user_full_name', $keyword); $this->db->or_like('x1.user_email', $keyword); $this->db->or_like('x1.user_url', $keyword); $this->db->or_like('x2.user_group', $keyword); $this->db->group_end(); } if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table . ' x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table . ' x1'); } /** * Check if email exists * @param String $user_email * @param Integer $id * @return Boolean */ public function email_exists( $user_email, $id = 0 ) { $this->db->where('user_email', $user_email); if ( _isNaturalNumber($id) ) $this->db->where('id <>', _toInteger($id)); $this->db->where('is_deleted', 'false'); $count = $this->db->count_all_results(self::$table); return $count > 0; } } PKr\B;3!M_admission_selection_process.phpnu[model->get_admission_year($admission_year_id); $fields = ['x1.id', 'x1.registration_number', 'x1.full_name']; if (__session('major_count') > 0) { array_push($fields, "COALESCE(x2.major_name, '') AS first_choice", "COALESCE(x3.major_name, '') AS second_choice"); } $this->db->select(implode(', ', $fields)); // If SMK or PT if (__session('major_count') > 0) { $this->db->join('majors x2', 'x1.first_choice_id = x2.id', 'LEFT'); $this->db->join('majors x3', 'x1.second_choice_id = x3.id', 'LEFT'); } $this->db->where('x1.is_deleted', 'false'); $this->db->where('x1.is_prospective_student', 'true'); $this->db->where('x1.re_registration', 'true'); $this->db->where('x1.selection_result IS NULL'); $this->db->where('x1.admission_type_id', $admission_type_id); $this->db->where('LEFT(x1.registration_number, 4) = ', $admission_year); if (__session('major_count') > 0) { $this->db->where('x1.first_choice_id', $major_id); } // Chek if min birth Date and max birth date isset $min_birth_date = __session('min_birth_date'); $max_birth_date = __session('max_birth_date'); if (NULL !== $min_birth_date && _isValidDate($min_birth_date) && NULL !== $max_birth_date && _isValidDate($max_birth_date)) { $birth_dates = array_date($min_birth_date, $max_birth_date); if (count($birth_dates) > 0) $this->db->where_in('x1.birth_date', $birth_dates); } if ( $return_type == 'count' ) return $this->db->count_all_results('students x1'); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get('students x1'); } /** * Selection Process * @param Integer $admission_year_id * @param Integer $admission_type_id * @param Any $selection_result * @param Array $student_ids * @return Boolean */ public function selection_process($admission_year_id = 0, $admission_type_id = 0, $selection_result, array $student_ids) { // Define Admission Year $admission_year = $this->model->get_admission_year($admission_year_id); // Default Quota $admission_quota = 0; // Check Quota $query = $this->db ->select('quota') ->where('academic_year_id', _toInteger($admission_year_id)) ->where('admission_type_id', _toInteger($admission_type_id)) ->where('major_id', _toInteger($selection_result)) ->get('admission_quotas'); if ($query->num_rows() === 1) { $res = $query->row(); $admission_quota = _toInteger($res->quota); } if ($selection_result != 'unapproved') { // Check Selection Result $approved = $this->db ->where('LEFT(registration_number, 4)=', $admission_year) ->where('admission_type_id', $admission_type_id) ->where('is_prospective_student', 'true') ->group_start() ->where('selection_result', $selection_result) ->or_where('selection_result', 'approved') ->group_end() ->count_all_results('students'); if (($admission_quota - $approved) < count($student_ids)) { return [ 'status' => 'warning', 'message' => 'Kuota pendaftaran tidak mencukupi. Silahkan periksa kembali pengaturan kuota pendaftaran.' ]; } } $this->db->set('selection_result', $selection_result); $this->db->set('updated_by', __session('user_id')); // If Approved / Diterima PPDB/PMB nya if ($selection_result != 'unapproved') { $student_status_id = get_option_id('student_status', 'aktif'); $this->db->set('is_student', 'true'); $this->db->set('student_status_id', _toInteger($student_status_id)); // Unapproved / Tidak Diterima } else { $this->db->set('is_student', 'false'); $this->db->set('student_status_id', NULL); } // update major_id if (_toInteger($selection_result) > 0) { $this->db->set('major_id', _toInteger($selection_result)); } $this->db->where_in('id', $student_ids); $query = $this->db->update('students'); return [ 'status' => $query ? 'success' : 'error', 'message' => $query ? 'Proses seleksi sudah tersimpan' : 'Proses seleksi tidak tersimpan' ]; } } PKr\QxM_subscribers.phpnu[db->select('id, email'); if ( ! empty($keyword) ) $this->db->like('email', $keyword); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } } PKr\kkM_user_groups.phpnu[db->select('id, user_group, is_deleted'); if ( ! empty($keyword) ) $this->db->like('user_group', $keyword); if ( $return_type == 'count' ) return $this->db->count_all_results(self::$table); if ( $limit > 0 ) $this->db->limit($limit, $offset); return $this->db->get(self::$table); } /** * Dropdown * @return Array */ public function dropdown() { $query = $this->db ->select('id, user_group') ->where('is_deleted', 'false') ->get(self::$table); $dataset = []; if ($query->num_rows() > 0) { foreach($query->result() as $row) { $dataset[$row->id] = $row->user_group; } } return $dataset; } } PKr\7 M_users.phpnu[db ->select('id , user_name , user_email , user_password , user_type , user_group_id , user_profile_id , has_login ') ->where('user_name', $user_name) ->where('is_deleted', 'false') ->limit(1) ->get(self::$table); } /** * last_logged_in() * @param Integer $id * @return void */ public function last_logged_in($id) { $fields = [ 'last_logged_in' => date('Y-m-d H:i:s'), 'ip_address' => get_ip_address(), 'has_login' => 'true' ]; $this->db ->where(self::$pk, $id) ->update(self::$table, $fields); } /** * Reset Logged In * set "has_login" to false * @param Integer $id * @return Void */ public function reset_logged_in($id) { $this->db ->where(self::$pk, $id) ->update(self::$table, ['has_login' => 'false']); } /** * get_attempts * @param String $ip_address * @return Object */ public function get_attempts($ip_address) { $query = $this->db ->where('ip_address', $ip_address) ->get('login_attempts'); if ($query->num_rows() === 1) { return $query->row(); } return NULL; } /** * increase_login_attempts * @param String $ip_address * @return Void */ public function increase_login_attempts($ip_address) { $query = $this->db ->where('ip_address', $ip_address) ->get('login_attempts'); if ($query->num_rows() === 1) { $result = $query->row(); $this->db ->where('ip_address', $ip_address) ->update('login_attempts', ['counter' => ($result->counter + 1)]); } else { $this->db ->insert('login_attempts', [ 'created_at' => date('Y-m-d H:i:s'), 'ip_address' => $ip_address, 'counter' => 1 ]); } } /** * Reset Attempts * @param String $ip_address * @return Void */ public function reset_attempts($ip_address) { $this->db ->where('ip_address', $ip_address) ->delete('login_attempts'); } /** * get last logged in * @return Resource */ public function get_last_login() { return $this->db ->select(" CASE WHEN x1.user_type = 'administrator' THEN x1.user_full_name WHEN x1.user_type = 'student' THEN x2.full_name WHEN x1.user_type = 'employee' THEN x3.full_name END AS full_name , x1.last_logged_in ") ->join('students x2', 'x1.user_profile_id = x2.id', 'LEFT') ->join('employees x3', 'x1.user_profile_id = x3.id', 'LEFT') ->where('x1.user_type !=', 'super_user') ->where('x1.last_logged_in IS NOT NULL') ->order_by('x1.last_logged_in', 'DESC') ->limit(10) ->get(self::$table.' x1'); } /** * Reset User Name * @param String $user_name * @return Boolean */ public function reset_user_name($user_name) { $user_id = __session('user_id'); $count = $this->db ->where('user_name', $user_name) ->where('id <> ', $user_id) ->count_all_results(self::$table); if ( $count == 0 ) { return $this->db ->where('id', $user_id) ->update(self::$table, ['user_name' => $user_name]); } return false; } /** * Reset User Email * @param String $user_email * @return Boolean */ public function reset_user_email($user_email) { $user_id = __session('user_id'); $count = $this->db ->where('user_email', $user_email) ->where('id <> ', $user_id) ->count_all_results(self::$table); if ( $count == 0 ) { return $this->db ->where('id', $user_id) ->update(self::$table, ['user_email' => $user_email]); } return false; } /** * set_forgot_password_key * @param String $user_email * @param String $user_forgot_password_key * @return Boolean */ public function set_forgot_password_key($user_email, $user_forgot_password_key) { $dataset = [ 'user_forgot_password_key' => $user_forgot_password_key, 'user_forgot_password_request_date' => date('Y-m-d H:i:s') ]; return $this->db ->where('user_email', $user_email) ->update(self::$table, $dataset); } /** * Remove Forgot Password Key * @param Integer $id * @return Boolean */ public function remove_forgot_password_key($id) { return $this->db ->where(self::$pk, $id) ->update(self::$table, [ 'user_forgot_password_key' => NULL, 'user_forgot_password_request_date' => NULL ]); } /** * Reset Password * @param String $id * @return Boolean */ public function reset_password( $id ) { return $this->db ->where(self::$pk, $id) ->update(self::$table, [ 'user_forgot_password_key' => NULL, 'user_forgot_password_request_date' => NULL, 'user_password' => password_hash($this->input->post('password', true), PASSWORD_BCRYPT) ]); } /** * Get user by email * @param String $user_email * @return Any */ public function get_user_by_email($user_email) { $query = $this->db ->where('user_email', $user_email) ->get(self::$table); if ($query->num_rows() === 1) { $result = $query->row(); return [ 'user_email' => $result->user_email, 'user_full_name' => $result->user_full_name ]; } return NULL; } /** * Get User ID * @param String $user_type * @param Integer $user_profile_id * @return Integer */ public function get_user_id( $user_type = 'student', $user_profile_id = 0 ) { $this->db->select('id'); $this->db->where('user_profile_id', $user_profile_id); $this->db->where('user_type', $user_type); $query = $this->db->get('users'); if ($query->num_rows() == 1) { $res = $query->row(); return $res->id; } return 0; } /** * Check if email exists * @param String $user_email * @param Integer $id * @return Boolean */ public function email_exists( $user_email, $id = 0 ) { $this->db->where('user_email', $user_email); if ( _isNaturalNumber($id) ) $this->db->where('id <>', _toInteger($id)); $this->db->where('is_deleted', 'false'); $count = $this->db->count_all_results(self::$table); return $count > 0; } } PKA \Go~~dom/model.min.jsnu[/** * TinyMCE version 7.7.1 (2025-03-05) */ !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.ModelManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(o=n=e,(r=String).prototype.isPrototypeOf(o)||(null===(s=n.constructor)||void 0===s?void 0:s.name)===r.name)?"string":t;var o,n,r,s})(t)===e,o=e=>t=>typeof t===e,n=e=>t=>e===t,r=t("string"),s=t("object"),l=t("array"),a=n(null),c=o("boolean"),i=n(void 0),m=e=>!(e=>null==e)(e),d=o("function"),u=o("number"),f=()=>{},g=e=>()=>e,h=e=>e,p=(e,t)=>e===t;function b(e,...t){return(...o)=>{const n=t.concat(o);return e.apply(null,n)}}const w=e=>t=>!e(t),v=e=>e(),y=g(!1),x=g(!0);class C{constructor(e,t){this.tag=e,this.value=t}static some(e){return new C(!0,e)}static none(){return C.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?C.some(e(this.value)):C.none()}bind(e){return this.tag?e(this.value):C.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:C.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return m(e)?C.some(e):C.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}C.singletonNone=new C(!1);const S=Array.prototype.slice,T=Array.prototype.indexOf,R=Array.prototype.push,D=(e,t)=>{return o=e,n=t,T.call(o,n)>-1;var o,n},O=(e,t)=>{for(let o=0,n=e.length;o{const o=[];for(let n=0;n{const o=e.length,n=new Array(o);for(let r=0;r{for(let o=0,n=e.length;o{const o=[],n=[];for(let r=0,s=e.length;r{const o=[];for(let n=0,r=e.length;n(((e,t)=>{for(let o=e.length-1;o>=0;o--)t(e[o],o)})(e,((e,n)=>{o=t(o,e,n)})),o),A=(e,t,o)=>(N(e,((e,n)=>{o=t(o,e,n)})),o),L=(e,t)=>((e,t,o)=>{for(let n=0,r=e.length;n{for(let o=0,n=e.length;o{const t=[];for(let o=0,n=e.length;oM(E(e,t)),P=(e,t)=>{for(let o=0,n=e.length;o{const o={};for(let n=0,r=e.length;nt>=0&&tF(e,0),$=e=>F(e,e.length-1),V=(e,t)=>{for(let o=0;o{const o=q(e);for(let n=0,r=o.length;nY(e,((e,o)=>({k:o,v:t(e,o)}))),Y=(e,t)=>{const o={};return G(e,((e,n)=>{const r=t(e,n);o[r.k]=r.v})),o},J=(e,t)=>{const o=[];return G(e,((e,n)=>{o.push(t(e,n))})),o},Q=e=>J(e,h),X=(e,t)=>U.call(e,t),Z="undefined"!=typeof window?window:Function("return this;")(),ee=(e,t)=>((e,t)=>{let o=null!=t?t:Z;for(let t=0;t{const t=ee("ownerDocument.defaultView",e);return s(e)&&((e=>((e,t)=>{const o=((e,t)=>ee(e,t))(e,t);if(null==o)throw new Error(e+" not available on this browser");return o})("HTMLElement",e))(t).prototype.isPrototypeOf(e)||/^HTML\w*Element$/.test(te(e).constructor.name))},ne=e=>e.dom.nodeName.toLowerCase(),re=e=>e.dom.nodeType,se=e=>t=>re(t)===e,le=e=>8===re(e)||"#comment"===ne(e),ae=e=>ce(e)&&oe(e.dom),ce=se(1),ie=se(3),me=se(9),de=se(11),ue=e=>t=>ce(t)&&ne(t)===e,fe=(e,t,o)=>{if(!(r(o)||c(o)||u(o)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",o,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,o+"")},ge=(e,t,o)=>{fe(e.dom,t,o)},he=(e,t)=>{const o=e.dom;G(t,((e,t)=>{fe(o,t,e)}))},pe=(e,t)=>{const o=e.dom.getAttribute(t);return null===o?void 0:o},be=(e,t)=>C.from(pe(e,t)),we=(e,t)=>{e.dom.removeAttribute(t)},ve=e=>A(e.dom.attributes,((e,t)=>(e[t.name]=t.value,e)),{}),ye=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},xe={fromHtml:(e,t)=>{const o=(t||document).createElement("div");if(o.innerHTML=e,!o.hasChildNodes()||o.childNodes.length>1){const t="HTML does not have a single root node";throw console.error(t,e),new Error(t)}return ye(o.childNodes[0])},fromTag:(e,t)=>{const o=(t||document).createElement(e);return ye(o)},fromText:(e,t)=>{const o=(t||document).createTextNode(e);return ye(o)},fromDom:ye,fromPoint:(e,t,o)=>C.from(e.dom.elementFromPoint(t,o)).map(ye)},Ce=(e,t)=>{const o=e.dom;if(1!==o.nodeType)return!1;{const e=o;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},Se=e=>1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType||0===e.childElementCount,Te=(e,t)=>{const o=void 0===t?document:t.dom;return Se(o)?C.none():C.from(o.querySelector(e)).map(xe.fromDom)},Re=(e,t)=>e.dom===t.dom,De=(e,t)=>{const o=e.dom,n=t.dom;return o!==n&&o.contains(n)},Oe=Ce,ke=e=>xe.fromDom(e.dom.ownerDocument),Ee=e=>me(e)?e:ke(e),Ne=e=>C.from(e.dom.parentNode).map(xe.fromDom),_e=e=>C.from(e.dom.parentElement).map(xe.fromDom),Be=(e,t)=>{const o=d(t)?t:y;let n=e.dom;const r=[];for(;null!==n.parentNode&&void 0!==n.parentNode;){const e=n.parentNode,t=xe.fromDom(e);if(r.push(t),!0===o(t))break;n=e}return r},ze=e=>C.from(e.dom.previousSibling).map(xe.fromDom),Ae=e=>C.from(e.dom.nextSibling).map(xe.fromDom),Le=e=>E(e.dom.childNodes,xe.fromDom),We=(e,t)=>{const o=e.dom.childNodes;return C.from(o[t]).map(xe.fromDom)},Me=(e,t)=>{Ne(e).each((o=>{o.dom.insertBefore(t.dom,e.dom)}))},je=(e,t)=>{Ae(e).fold((()=>{Ne(e).each((e=>{Ie(e,t)}))}),(e=>{Me(e,t)}))},Pe=(e,t)=>{const o=(e=>We(e,0))(e);o.fold((()=>{Ie(e,t)}),(o=>{e.dom.insertBefore(t.dom,o.dom)}))},Ie=(e,t)=>{e.dom.appendChild(t.dom)},Fe=(e,t)=>{Me(e,t),Ie(t,e)},He=(e,t)=>{N(t,((o,n)=>{const r=0===n?e:t[n-1];je(r,o)}))},$e=(e,t)=>{N(t,(t=>{Ie(e,t)}))},Ve=e=>{e.dom.textContent="",N(Le(e),(e=>{qe(e)}))},qe=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)},Ue=e=>{const t=Le(e);t.length>0&&He(e,t),qe(e)},Ge=(e,t)=>xe.fromDom(e.dom.cloneNode(t)),Ke=e=>Ge(e,!1),Ye=e=>Ge(e,!0),Je=(e,t)=>{const o=xe.fromTag(t),n=ve(e);return he(o,n),o},Qe=["tfoot","thead","tbody","colgroup"],Xe=(e,t,o)=>({element:e,rowspan:t,colspan:o}),Ze=(e,t,o)=>({element:e,cells:t,section:o}),et=(e,t,o)=>({element:e,isNew:t,isLocked:o}),tt=(e,t,o,n)=>({element:e,cells:t,section:o,isNew:n}),ot=e=>de(e)&&m(e.dom.host),nt=e=>xe.fromDom(e.dom.getRootNode()),rt=e=>xe.fromDom(e.dom.host),st=e=>{const t=ie(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const o=t.ownerDocument;return(e=>{const t=nt(e);return ot(t)?C.some(t):C.none()})(xe.fromDom(t)).fold((()=>o.body.contains(t)),(n=st,r=rt,e=>n(r(e))));var n,r},lt=()=>at(xe.fromDom(document)),at=e=>{const t=e.dom.body;if(null==t)throw new Error("Body is not available yet");return xe.fromDom(t)},ct=(e,t)=>{let o=[];return N(Le(e),(e=>{t(e)&&(o=o.concat([e])),o=o.concat(ct(e,t))})),o},it=(e,t,o)=>((e,o,n)=>B(Be(e,n),(e=>Ce(e,t))))(e,0,o),mt=(e,t)=>(e=>B(Le(e),(e=>Ce(e,t))))(e),dt=(e,t)=>((e,t)=>{const o=void 0===t?document:t.dom;return Se(o)?[]:E(o.querySelectorAll(e),xe.fromDom)})(t,e);var ut=(e,t,o,n,r)=>e(o,n)?C.some(o):d(r)&&r(o)?C.none():t(o,n,r);const ft=(e,t,o)=>{let n=e.dom;const r=d(o)?o:y;for(;n.parentNode;){n=n.parentNode;const e=xe.fromDom(n);if(t(e))return C.some(e);if(r(e))break}return C.none()},gt=(e,t,o)=>ut(((e,t)=>t(e)),ft,e,t,o),ht=(e,t,o)=>ft(e,(e=>Ce(e,t)),o),pt=(e,t)=>(e=>L(e.dom.childNodes,(e=>{return o=xe.fromDom(e),Ce(o,t);var o})).map(xe.fromDom))(e),bt=(e,t)=>Te(t,e),wt=(e,t,o)=>ut(((e,t)=>Ce(e,t)),ht,e,t,o),vt=(e,t,o=p)=>e.exists((e=>o(e,t))),yt=e=>{const t=[],o=e=>{t.push(e)};for(let t=0;te?C.some(t):C.none(),Ct=(e,t,o)=>""===t||e.length>=t.length&&e.substr(o,o+t.length)===t,St=(e,t,o=0,n)=>{const r=e.indexOf(t,o);return-1!==r&&(!!i(n)||r+t.length<=n)},Tt=(e,t)=>Ct(e,t,0),Rt=(e,t)=>Ct(e,t,e.length-t.length),Dt=(e=>t=>t.replace(e,""))(/^\s+|\s+$/g),Ot=e=>e.length>0,kt=e=>void 0!==e.style&&d(e.style.getPropertyValue),Et=(e,t,o)=>{if(!r(o))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",o,":: Element ",e),new Error("CSS value must be a string: "+o);kt(e)&&e.style.setProperty(t,o)},Nt=(e,t,o)=>{const n=e.dom;Et(n,t,o)},_t=(e,t)=>{const o=e.dom;G(t,((e,t)=>{Et(o,t,e)}))},Bt=(e,t)=>{const o=e.dom,n=window.getComputedStyle(o).getPropertyValue(t);return""!==n||st(e)?n:zt(o,t)},zt=(e,t)=>kt(e)?e.style.getPropertyValue(t):"",At=(e,t)=>{const o=e.dom,n=zt(o,t);return C.from(n).filter((e=>e.length>0))},Lt=(e,t)=>{((e,t)=>{kt(e)&&e.style.removeProperty(t)})(e.dom,t),vt(be(e,"style").map(Dt),"")&&we(e,"style")},Wt=(e,t,o=0)=>be(e,t).map((e=>parseInt(e,10))).getOr(o),Mt=(e,t)=>Wt(e,t,1),jt=e=>ue("col")(e)?Wt(e,"span",1)>1:Mt(e,"colspan")>1,Pt=(e,t)=>parseInt(Bt(e,t),10),It=g(10),Ft=g(10),Ht=(e,t)=>$t(e,t,x),$t=(e,t,o)=>j(Le(e),(e=>Ce(e,t)?o(e)?[e]:[]:$t(e,t,o))),Vt=(e,t)=>((e,t,o=y)=>o(t)?C.none():D(e,ne(t))?C.some(t):ht(t,e.join(","),(e=>Ce(e,"table")||o(e))))(["td","th"],e,t),qt=e=>Ht(e,"th,td"),Ut=e=>Ce(e,"colgroup")?mt(e,"col"):j(Yt(e),(e=>mt(e,"col"))),Gt=(e,t)=>wt(e,"table",t),Kt=e=>Ht(e,"tr"),Yt=e=>Gt(e).fold(g([]),(e=>mt(e,"colgroup"))),Jt=(e,t)=>E(e,(e=>{if("colgroup"===ne(e)){const t=E(Ut(e),(e=>{const t=Wt(e,"span",1);return Xe(e,1,t)}));return Ze(e,t,"colgroup")}{const o=E(qt(e),(e=>{const t=Wt(e,"rowspan",1),o=Wt(e,"colspan",1);return Xe(e,t,o)}));return Ze(e,o,t(e))}})),Qt=e=>Ne(e).map((e=>{const t=ne(e);return(e=>D(Qe,e))(t)?t:"tbody"})).getOr("tbody"),Xt=e=>{const t=Kt(e),o=[...Yt(e),...t];return Jt(o,Qt)},Zt=e=>{let t,o=!1;return(...n)=>(o||(o=!0,t=e.apply(null,n)),t)},eo=()=>to(0,0),to=(e,t)=>({major:e,minor:t}),oo={nu:to,detect:(e,t)=>{const o=String(t).toLowerCase();return 0===e.length?eo():((e,t)=>{const o=((e,t)=>{for(let o=0;oNumber(t.replace(o,"$"+e));return to(n(1),n(2))})(e,o)},unknown:eo},no=(e,t)=>{const o=String(t).toLowerCase();return L(e,(e=>e.search(o)))},ro=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,so=e=>t=>St(t,e),lo=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>St(e,"edge/")&&St(e,"chrome")&&St(e,"safari")&&St(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,ro],search:e=>St(e,"chrome")&&!St(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>St(e,"msie")||St(e,"trident")},{name:"Opera",versionRegexes:[ro,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:so("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:so("firefox")},{name:"Safari",versionRegexes:[ro,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(St(e,"safari")||St(e,"mobile/"))&&St(e,"applewebkit")}],ao=[{name:"Windows",search:so("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>St(e,"iphone")||St(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:so("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:so("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:so("linux"),versionRegexes:[]},{name:"Solaris",search:so("sunos"),versionRegexes:[]},{name:"FreeBSD",search:so("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:so("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],co={browsers:g(lo),oses:g(ao)},io="Edge",mo="Chromium",uo="Opera",fo="Firefox",go="Safari",ho=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isEdge:n(io),isChromium:n(mo),isIE:n("IE"),isOpera:n(uo),isFirefox:n(fo),isSafari:n(go)}},po=()=>ho({current:void 0,version:oo.unknown()}),bo=ho,wo=(g(io),g(mo),g("IE"),g(uo),g(fo),g(go),"Windows"),vo="Android",yo="Linux",xo="macOS",Co="Solaris",So="FreeBSD",To="ChromeOS",Ro=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isWindows:n(wo),isiOS:n("iOS"),isAndroid:n(vo),isMacOS:n(xo),isLinux:n(yo),isSolaris:n(Co),isFreeBSD:n(So),isChromeOS:n(To)}},Do=()=>Ro({current:void 0,version:oo.unknown()}),Oo=Ro,ko=(g(wo),g("iOS"),g(vo),g(yo),g(xo),g(Co),g(So),g(To),e=>window.matchMedia(e).matches);let Eo=Zt((()=>((e,t,o)=>{const n=co.browsers(),r=co.oses(),s=t.bind((e=>((e,t)=>V(t.brands,(t=>{const o=t.brand.toLowerCase();return L(e,(e=>{var t;return o===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:oo.nu(parseInt(t.version,10),0)})))})))(n,e))).orThunk((()=>((e,t)=>no(e,t).map((e=>{const o=oo.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(n,e))).fold(po,bo),l=((e,t)=>no(e,t).map((e=>{const o=oo.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(r,e).fold(Do,Oo),a=((e,t,o,n)=>{const r=e.isiOS()&&!0===/ipad/i.test(o),s=e.isiOS()&&!r,l=e.isiOS()||e.isAndroid(),a=l||n("(pointer:coarse)"),c=r||!s&&l&&n("(min-device-width:768px)"),i=s||l&&!c,m=t.isSafari()&&e.isiOS()&&!1===/safari/i.test(o),d=!i&&!c&&!m;return{isiPad:g(r),isiPhone:g(s),isTablet:g(c),isPhone:g(i),isTouch:g(a),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:g(m),isDesktop:g(d)}})(l,s,e,o);return{browser:s,os:l,deviceType:a}})(window.navigator.userAgent,C.from(window.navigator.userAgentData),ko)));const No=()=>Eo(),_o=(e,t)=>{const o=o=>{const n=t(o);if(n<=0||null===n){const t=Bt(o,e);return parseFloat(t)||0}return n},n=(e,t)=>A(t,((t,o)=>{const n=Bt(e,o),r=void 0===n?0:parseInt(n,10);return isNaN(r)?t:t+r}),0);return{set:(t,o)=>{if(!u(o)&&!o.match(/^[0-9]+$/))throw new Error(e+".set accepts only positive integer values. Value was "+o);const n=t.dom;kt(n)&&(n.style[e]=o+"px")},get:o,getOuter:o,aggregate:n,max:(e,t,o)=>{const r=n(e,o);return t>r?t-r:0}}},Bo=(e,t,o)=>((e,t)=>(e=>{const t=parseFloat(e);return isNaN(t)?C.none():C.some(t)})(e).getOr(t))(Bt(e,t),o),zo=_o("width",(e=>e.dom.offsetWidth)),Ao=e=>zo.get(e),Lo=e=>zo.getOuter(e),Wo=e=>((e,t)=>{const o=e.dom,n=o.getBoundingClientRect().width||o.offsetWidth;return"border-box"===t?n:((e,t,o,n)=>t-Bo(e,`padding-${o}`,0)-Bo(e,`padding-${n}`,0)-Bo(e,`border-${o}-width`,0)-Bo(e,`border-${n}-width`,0))(e,n,"left","right")})(e,"content-box"),Mo=(e,t,o)=>{const n=e.cells,r=n.slice(0,t),s=n.slice(t),l=r.concat(o).concat(s);return Io(e,l)},jo=(e,t,o)=>Mo(e,t,[o]),Po=(e,t,o)=>{e.cells[t]=o},Io=(e,t)=>tt(e.element,t,e.section,e.isNew),Fo=(e,t)=>e.cells[t],Ho=(e,t)=>Fo(e,t).element,$o=e=>e.cells.length,Vo=e=>{const t=_(e,(e=>"colgroup"===e.section));return{rows:t.fail,cols:t.pass}},qo=(e,t,o)=>{const n=E(e.cells,o);return tt(t(e.element),n,e.section,!0)},Uo="data-snooker-locked-cols",Go=e=>be(e,Uo).bind((e=>C.from(e.match(/\d+/g)))).map((e=>I(e,x))),Ko=e=>{const t=A(Vo(e).rows,((e,t)=>(N(t.cells,((t,o)=>{t.isLocked&&(e[o]=!0)})),e)),{}),o=J(t,((e,t)=>parseInt(t,10)));return(e=>{const t=S.call(e,0);return t.sort(void 0),t})(o)},Yo=(e,t)=>e+","+t,Jo=(e,t)=>{const o=j(e.all,(e=>e.cells));return B(o,t)},Qo=e=>{const t={},o=[],n=H(e).map((e=>e.element)).bind(Gt).bind(Go).getOr({});let r=0,s=0,l=0;const{pass:a,fail:c}=_(e,(e=>"colgroup"===e.section));N(c,(e=>{const a=[];N(e.cells,(e=>{let o=0;for(;void 0!==t[Yo(l,o)];)o++;const r=((e,t)=>X(e,t)&&void 0!==e[t]&&null!==e[t])(n,o.toString()),c=((e,t,o,n,r,s)=>({element:e,rowspan:t,colspan:o,row:n,column:r,isLocked:s}))(e.element,e.rowspan,e.colspan,l,o,r);for(let n=0;n{const t=(e=>{const t={};let o=0;return N(e.cells,(e=>{const n=e.colspan;k(n,(r=>{const s=o+r;t[s]=((e,t,o)=>({element:e,colspan:t,column:o}))(e.element,n,s)})),o+=n})),t})(e),o=((e,t)=>({element:e,columns:t}))(e.element,Q(t));return{colgroups:[o],columns:t}})).getOrThunk((()=>({colgroups:[],columns:{}}))),d=((e,t)=>({rows:e,columns:t}))(r,s);return{grid:d,access:t,all:o,columns:i,colgroups:m}},Xo=e=>{const t=Xt(e);return Qo(t)},Zo=Qo,en=(e,t,o)=>C.from(e.access[Yo(t,o)]),tn=(e,t,o)=>{const n=Jo(e,(e=>o(t,e.element)));return n.length>0?C.some(n[0]):C.none()},on=Jo,nn=e=>j(e.all,(e=>e.cells)),rn=e=>Q(e.columns),sn=e=>q(e.columns).length>0,ln=(e,t)=>C.from(e.columns[t]),an=(e,t=x)=>{const o=e.grid,n=k(o.columns,h),r=k(o.rows,h);return E(n,(o=>cn((()=>j(r,(t=>en(e,t,o).filter((e=>e.column===o)).toArray()))),(e=>1===e.colspan&&t(e.element)),(()=>en(e,0,o)))))},cn=(e,t,o)=>{const n=e();return L(n,t).orThunk((()=>C.from(n[0]).orThunk(o))).map((e=>e.element))},mn=e=>{const t=e.grid,o=k(t.rows,h),n=k(t.columns,h);return E(o,(t=>cn((()=>j(n,(o=>en(e,t,o).filter((e=>e.row===t)).fold(g([]),(e=>[e]))))),(e=>1===e.rowspan),(()=>en(e,t,0)))))},dn=(e,t)=>o=>"rtl"===un(o)?t:e,un=e=>"rtl"===Bt(e,"direction")?"rtl":"ltr",fn=_o("height",(e=>{const t=e.dom;return st(e)?t.getBoundingClientRect().height:t.offsetHeight})),gn=e=>fn.get(e),hn=e=>fn.getOuter(e),pn=(e,t)=>({left:e,top:t,translate:(o,n)=>pn(e+o,t+n)}),bn=pn,wn=(e,t)=>void 0!==e?e:void 0!==t?t:0,vn=e=>{const t=e.dom.ownerDocument,o=t.body,n=t.defaultView,r=t.documentElement;if(o===e.dom)return bn(o.offsetLeft,o.offsetTop);const s=wn(null==n?void 0:n.pageYOffset,r.scrollTop),l=wn(null==n?void 0:n.pageXOffset,r.scrollLeft),a=wn(r.clientTop,o.clientTop),c=wn(r.clientLeft,o.clientLeft);return yn(e).translate(l-c,s-a)},yn=e=>{const t=e.dom,o=t.ownerDocument.body;return o===t?bn(o.offsetLeft,o.offsetTop):st(e)?(e=>{const t=e.getBoundingClientRect();return bn(t.left,t.top)})(t):bn(0,0)},xn=(e,t)=>({row:e,y:t}),Cn=(e,t)=>({col:e,x:t}),Sn=e=>vn(e).left+Lo(e),Tn=e=>vn(e).left,Rn=(e,t)=>Cn(e,Tn(t)),Dn=(e,t)=>Cn(e,Sn(t)),On=e=>vn(e).top,kn=(e,t)=>xn(e,On(t)),En=(e,t)=>xn(e,On(t)+hn(t)),Nn=(e,t,o)=>{if(0===o.length)return[];const n=E(o.slice(1),((t,o)=>t.map((t=>e(o,t))))),r=o[o.length-1].map((e=>t(o.length-1,e)));return n.concat([r])},_n={delta:h,positions:e=>Nn(kn,En,e),edge:On},Bn=dn({delta:h,edge:Tn,positions:e=>Nn(Rn,Dn,e)},{delta:e=>-e,edge:Sn,positions:e=>Nn(Dn,Rn,e)}),zn={delta:(e,t)=>Bn(t).delta(e,t),positions:(e,t)=>Bn(t).positions(e,t),edge:e=>Bn(e).edge(e)},An={unsupportedLength:["em","ex","cap","ch","ic","rem","lh","rlh","vw","vh","vi","vb","vmin","vmax","cm","mm","Q","in","pc","pt","px"],fixed:["px","pt"],relative:["%"],empty:[""]},Ln=(()=>{const e="[0-9]+",t="[eE][+-]?"+e,o=e=>`(?:${e})?`,n=["Infinity",e+"\\."+o(e)+o(t),"\\."+e+o(t),e+o(t)].join("|");return new RegExp(`^([+-]?(?:${n}))(.*)$`)})(),Wn=/(\d+(\.\d+)?)%/,Mn=/(\d+(\.\d+)?)px|em/,jn=ue("col"),Pn=ue("tr"),In=(e,t,o)=>{const n=_e(e).getOrThunk((()=>at(ke(e))));return t(e)/o(n)*100},Fn=(e,t)=>{Nt(e,"width",t+"px")},Hn=(e,t)=>{Nt(e,"width",t+"%")},$n=(e,t)=>{Nt(e,"height",t+"px")},Vn=e=>{const t=(e=>{return Bo(t=e,"height",t.dom.offsetHeight)+"px";var t})(e);return t?((e,t,o,n)=>{const r=parseFloat(e);return Rt(e,"%")&&"table"!==ne(t)?((e,t,o,n)=>{const r=Gt(e).map((e=>{const n=o(e);return Math.floor(t/100*n)})).getOr(t);return n(e,r),r})(t,r,o,n):r})(t,e,gn,$n):gn(e)},qn=(e,t)=>At(e,t).orThunk((()=>be(e,t).map((e=>e+"px")))),Un=e=>qn(e,"width"),Gn=e=>In(e,Ao,Wo),Kn=e=>{return jn(e)?Ao(e):Bo(t=e,"width",t.dom.offsetWidth);var t},Yn=e=>Pn(e)?gn(e):((e,t,o)=>o(e)/Mt(e,"rowspan"))(e,0,Vn),Jn=(e,t,o)=>{Nt(e,"width",t+o)},Qn=e=>In(e,Ao,Wo)+"%",Xn=g(Wn),Zn=ue("col"),er=e=>Un(e).getOrThunk((()=>Kn(e)+"px")),tr=e=>{return(t=e,qn(t,"height")).getOrThunk((()=>Yn(e)+"px"));var t},or=(e,t,o,n,r,s)=>e.filter(n).fold((()=>s(((e,t)=>{if(t<0||t>=e.length-1)return C.none();const o=e[t].fold((()=>{const o=(e=>{const t=S.call(e,0);return t.reverse(),t})(e.slice(0,t));return V(o,((e,t)=>e.map((e=>({value:e,delta:t+1})))))}),(e=>C.some({value:e,delta:0}))),n=e[t+1].fold((()=>{const o=e.slice(t+1);return V(o,((e,t)=>e.map((e=>({value:e,delta:t+1})))))}),(e=>C.some({value:e,delta:1})));return o.bind((e=>n.map((t=>{const o=t.delta+e.delta;return Math.abs(t.value-e.value)/o}))))})(o,t))),(e=>r(e))),nr=(e,t,o,n)=>{const r=an(e),s=sn(e)?(e=>E(rn(e),(e=>C.from(e.element))))(e):r,l=[C.some(zn.edge(t))].concat(E(zn.positions(r,t),(e=>e.map((e=>e.x))))),a=w(jt);return E(s,((e,t)=>or(e,t,l,a,(e=>{if((e=>{const t=No().browser,o=t.isChromium()||t.isFirefox();return!Zn(e)||o})(e))return o(e);{const e=null!=(s=r[t])?h(s):C.none();return or(e,t,l,a,(e=>n(C.some(Ao(e)))),n)}var s}),n)))},rr=e=>e.map((e=>e+"px")).getOr(""),sr=(e,t,o)=>nr(e,t,Kn,(e=>e.getOrThunk(o.minCellWidth))),lr=(e,t,o,n)=>{const r=mn(e),s=E(e.all,(e=>C.some(e.element))),l=[C.some(_n.edge(t))].concat(E(_n.positions(r,t),(e=>e.map((e=>e.y)))));return E(s,((e,t)=>or(e,t,l,x,o,n)))},ar=(e,t)=>()=>st(e)?t(e):parseFloat(At(e,"width").getOr("0")),cr=e=>{const t=ar(e,(e=>parseFloat(Qn(e)))),o=ar(e,Ao);return{width:t,pixelWidth:o,getWidths:(t,o)=>((e,t,o)=>nr(e,t,Gn,(e=>e.fold((()=>o.minCellWidth()),(e=>e/o.pixelWidth()*100)))))(t,e,o),getCellDelta:e=>e/o()*100,singleColumnWidth:(e,t)=>[100-e],minCellWidth:()=>It()/o()*100,setElementWidth:Hn,adjustTableWidth:o=>{const n=t();Hn(e,n+o/100*n)},isRelative:!0,label:"percent"}},ir=e=>{const t=ar(e,Ao);return{width:t,pixelWidth:t,getWidths:(t,o)=>sr(t,e,o),getCellDelta:h,singleColumnWidth:(e,t)=>[Math.max(It(),e+t)-e],minCellWidth:It,setElementWidth:Fn,adjustTableWidth:o=>{const n=t()+o;Fn(e,n)},isRelative:!1,label:"pixel"}},mr=e=>Un(e).fold((()=>(e=>{const t=ar(e,Ao),o=g(0);return{width:t,pixelWidth:t,getWidths:(t,o)=>sr(t,e,o),getCellDelta:o,singleColumnWidth:g([0]),minCellWidth:o,setElementWidth:f,adjustTableWidth:f,isRelative:!0,label:"none"}})(e)),(t=>((e,t)=>null!==Xn().exec(t)?cr(e):ir(e))(e,t))),dr=ir,ur=cr,fr=(e,t,o)=>{const n=e[o].element,r=xe.fromTag("td");Ie(r,xe.fromTag("br")),(t?Ie:Pe)(n,r)},gr=(e=>{const t=t=>e(t)?C.from(t.dom.nodeValue):C.none();return{get:o=>{if(!e(o))throw new Error("Can only get text value of a text node");return t(o).getOr("")},getOption:t,set:(t,o)=>{if(!e(t))throw new Error("Can only set raw text value of a text node");t.dom.nodeValue=o}}})(ie),hr=e=>gr.get(e),pr=e=>gr.getOption(e),br=(e,t)=>gr.set(e,t),wr=e=>"img"===ne(e)?1:pr(e).fold((()=>Le(e).length),(e=>e.length)),vr=["img","br"],yr=e=>pr(e).filter((e=>0!==e.trim().length||e.indexOf("\xa0")>-1)).isSome()||D(vr,ne(e))||(e=>ae(e)&&"false"===pe(e,"contenteditable"))(e),xr=e=>((e,t)=>{const o=e=>{for(let n=0;nSr(e,yr),Sr=(e,t)=>{const o=e=>{const n=Le(e);for(let e=n.length-1;e>=0;e--){const r=n[e];if(t(r))return C.some(r);const s=o(r);if(s.isSome())return s}return C.none()};return o(e)},Tr={scope:["row","col"]},Rr=e=>()=>{const t=xe.fromTag("td",e.dom);return Ie(t,xe.fromTag("br",e.dom)),t},Dr=e=>()=>xe.fromTag("col",e.dom),Or=e=>()=>xe.fromTag("colgroup",e.dom),kr=e=>()=>xe.fromTag("tr",e.dom),Er=(e,t,o)=>{const n=((e,t)=>{const o=Je(e,t),n=Le(Ye(e));return $e(o,n),o})(e,t);return G(o,((e,t)=>{null===e?we(n,t):ge(n,t,e)})),n},Nr=e=>e,_r=(e,t,o)=>{const n=(e,t)=>{((e,t)=>{const o=e.dom,n=t.dom;kt(o)&&kt(n)&&(n.style.cssText=o.style.cssText)})(e.element,t),Lt(t,"height"),1!==e.colspan&&Lt(t,"width")};return{col:o=>{const r=xe.fromTag(ne(o.element),t.dom);return n(o,r),e(o.element,r),r},colgroup:Or(t),row:kr(t),cell:r=>{const s=xe.fromTag(ne(r.element),t.dom),l=o.getOr(["strong","em","b","i","span","font","h1","h2","h3","h4","h5","h6","p","div"]),a=l.length>0?((e,t,o)=>xr(e).map((n=>{const r=o.join(","),s=it(n,r,(t=>Re(t,e)));return z(s,((e,t)=>{const o=Ke(t);return Ie(e,o),o}),t)})).getOr(t))(r.element,s,l):s;return Ie(a,xe.fromTag("br")),n(r,s),((e,t)=>{G(Tr,((o,n)=>be(e,n).filter((e=>D(o,e))).each((e=>ge(t,n,e)))))})(r.element,s),e(r.element,s),s},replace:Er,colGap:Dr(t),gap:Rr(t)}},Br=e=>({col:Dr(e),colgroup:Or(e),row:kr(e),cell:Rr(e),replace:Nr,colGap:Dr(e),gap:Rr(e)}),zr=e=>t=>t.options.get(e),Ar="100%",Lr=e=>{var t;const o=e.dom,n=null!==(t=o.getParent(e.selection.getStart(),o.isBlock))&&void 0!==t?t:e.getBody();return Wo(xe.fromDom(n))+"px"},Wr=e=>C.from(e.options.get("table_clone_elements")),Mr=zr("table_header_type"),jr=zr("table_column_resizing"),Pr=e=>"preservetable"===jr(e),Ir=e=>"resizetable"===jr(e),Fr=zr("table_sizing_mode"),Hr=e=>"relative"===Fr(e),$r=e=>"fixed"===Fr(e),Vr=e=>"responsive"===Fr(e),qr=zr("table_resize_bars"),Ur=zr("table_style_by_css"),Gr=zr("table_merge_content_on_paste"),Kr=e=>{const t=e.options,o=t.get("table_default_attributes");return t.isSet("table_default_attributes")?o:((e,t)=>Vr(e)||Ur(e)?t:$r(e)?{...t,width:Lr(e)}:{...t,width:Ar})(e,o)},Yr=zr("table_use_colgroups"),Jr=zr("fixed_toolbar_container"),Qr=zr("fixed_toolbar_container_target"),Xr=zr("ui_mode"),Zr=e=>wt(e,"[contenteditable]"),es=(e,t=!1)=>st(e)?e.dom.isContentEditable:Zr(e).fold(g(t),(e=>"true"===ts(e))),ts=e=>e.dom.contentEditable,os=e=>xe.fromDom(e.getBody()),ns=e=>t=>Re(t,os(e)),rs=e=>{we(e,"data-mce-style");const t=e=>we(e,"data-mce-style");N(qt(e),t),N(Ut(e),t),N(Kt(e),t)},ss=e=>xe.fromDom(e.selection.getStart()),ls=e=>e.getBoundingClientRect().width,as=e=>e.getBoundingClientRect().height,cs=e=>(t,o)=>{const n=t.dom.getStyle(o,e)||t.dom.getAttrib(o,e);return C.from(n).filter(Ot)},is=cs("width"),ms=cs("height"),ds=e=>gt(e,ue("table")).exists(es),us=(e,t)=>{const o=t.column,n=t.column+t.colspan-1,r=t.row,s=t.row+t.rowspan-1;return o<=e.finishCol&&n>=e.startCol&&r<=e.finishRow&&s>=e.startRow},fs=(e,t)=>t.column>=e.startCol&&t.column+t.colspan-1<=e.finishCol&&t.row>=e.startRow&&t.row+t.rowspan-1<=e.finishRow,gs=(e,t,o)=>{const n=tn(e,t,Re),r=tn(e,o,Re);return n.bind((e=>r.map((t=>{return o=e,n=t,{startRow:Math.min(o.row,n.row),startCol:Math.min(o.column,n.column),finishRow:Math.max(o.row+o.rowspan-1,n.row+n.rowspan-1),finishCol:Math.max(o.column+o.colspan-1,n.column+n.colspan-1)};var o,n}))))},hs=(e,t,o)=>gs(e,t,o).map((t=>{const o=on(e,b(us,t));return E(o,(e=>e.element))})),ps=(e,t)=>tn(e,t,((e,t)=>De(t,e))).map((e=>e.element)),bs=(e,t,o)=>{const n=vs(e);return hs(n,t,o)},ws=(e,t,o,n,r)=>{const s=vs(e),l=Re(e,o)?C.some(t):ps(s,t),a=Re(e,r)?C.some(n):ps(s,n);return l.bind((e=>a.bind((t=>hs(s,e,t)))))},vs=Xo;var ys=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","li","table","thead","tbody","tfoot","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"],xs=()=>({up:g({selector:ht,closest:wt,predicate:ft,all:Be}),down:g({selector:dt,predicate:ct}),styles:g({get:Bt,getRaw:At,set:Nt,remove:Lt}),attrs:g({get:pe,set:ge,remove:we,copyTo:(e,t)=>{const o=ve(e);he(t,o)}}),insert:g({before:Me,after:je,afterAll:He,append:Ie,appendAll:$e,prepend:Pe,wrap:Fe}),remove:g({unwrap:Ue,remove:qe}),create:g({nu:xe.fromTag,clone:e=>xe.fromDom(e.dom.cloneNode(!1)),text:xe.fromText}),query:g({comparePosition:(e,t)=>e.dom.compareDocumentPosition(t.dom),prevSibling:ze,nextSibling:Ae}),property:g({children:Le,name:ne,parent:Ne,document:e=>Ee(e).dom,isText:ie,isComment:le,isElement:ce,isSpecial:e=>{const t=ne(e);return D(["script","noscript","iframe","noframes","noembed","title","style","textarea","xmp"],t)},getLanguage:e=>ce(e)?be(e,"lang"):C.none(),getText:hr,setText:br,isBoundary:e=>!!ce(e)&&("body"===ne(e)||D(ys,ne(e))),isEmptyTag:e=>!!ce(e)&&D(["br","img","hr","input"],ne(e)),isNonEditable:e=>ce(e)&&"false"===pe(e,"contenteditable")}),eq:Re,is:Oe});const Cs=(e,t,o,n)=>{const r=t(e,o);return z(n,((o,n)=>{const r=t(e,n);return Ss(e,o,r)}),r)},Ss=(e,t,o)=>t.bind((t=>o.filter(b(e.eq,t)))),Ts=xs(),Rs=(e,t)=>((e,t,o)=>o.length>0?((e,t,o,n)=>n(e,t,o[0],o.slice(1)))(e,t,o,Cs):C.none())(Ts,((t,o)=>e(o)),t),Ds=e=>ht(e,"table"),Os=(e,t,o)=>{const n=e=>t=>void 0!==o&&o(t)||Re(t,e);return Re(e,t)?C.some({boxes:C.some([e]),start:e,finish:t}):Ds(e).bind((r=>Ds(t).bind((s=>{if(Re(r,s))return C.some({boxes:bs(r,e,t),start:e,finish:t});if(De(r,s)){const o=it(t,"td,th",n(r)),l=o.length>0?o[o.length-1]:t;return C.some({boxes:ws(r,e,r,t,s),start:e,finish:l})}if(De(s,r)){const o=it(e,"td,th",n(s)),l=o.length>0?o[o.length-1]:e;return C.some({boxes:ws(s,e,r,t,s),start:e,finish:l})}return((e,t)=>((e,t,o,n=y)=>{const r=[t].concat(e.up().all(t)),s=[o].concat(e.up().all(o)),l=e=>W(e,n).fold((()=>e),(t=>e.slice(0,t+1))),a=l(r),c=l(s),i=L(a,(t=>O(c,((e,t)=>b(e.eq,t))(e,t))));return{firstpath:a,secondpath:c,shared:i}})(Ts,e,t,void 0))(e,t).shared.bind((l=>wt(l,"table",o).bind((o=>{const l=it(t,"td,th",n(o)),a=l.length>0?l[l.length-1]:t,c=it(e,"td,th",n(o)),i=c.length>0?c[c.length-1]:e;return C.some({boxes:ws(o,e,r,t,s),start:i,finish:a})}))))}))))},ks=(e,t)=>{const o=dt(e,t);return o.length>0?C.some(o):C.none()},Es=(e,t,o)=>bt(e,t).bind((t=>bt(e,o).bind((e=>Rs(Ds,[t,e]).map((o=>({first:t,last:e,table:o}))))))),Ns=(e,t,o,n,r)=>((e,t)=>L(e,(e=>Ce(e,t))))(e,r).bind((e=>((e,t,o)=>Gt(e).bind((n=>((e,t,o,n)=>tn(e,t,Re).bind((t=>{const r=o>0?t.row+t.rowspan-1:t.row,s=n>0?t.column+t.colspan-1:t.column;return en(e,r+o,s+n).map((e=>e.element))})))(vs(n),e,t,o))))(e,t,o).bind((e=>((e,t)=>ht(e,"table").bind((o=>bt(o,t).bind((t=>Os(t,e).bind((e=>e.boxes.map((t=>({boxes:t,start:e.start,finish:e.finish}))))))))))(e,n))))),_s=(e,t)=>ks(e,t),Bs=(e,t,o)=>Es(e,t,o).bind((t=>{const o=t=>Re(e,t),n="thead,tfoot,tbody,table",r=ht(t.first,n,o),s=ht(t.last,n,o);return r.bind((e=>s.bind((o=>Re(e,o)?((e,t,o)=>((e,t,o)=>gs(e,t,o).bind((t=>((e,t)=>{let o=!0;const n=b(fs,t);for(let r=t.startRow;r<=t.finishRow;r++)for(let s=t.startCol;s<=t.finishCol;s++)o=o&&en(e,r,s).exists(n);return o?C.some(t):C.none()})(e,t))))(vs(e),t,o))(t.table,t.first,t.last):C.none()))))})),zs=h,As=e=>{const t=(e,t)=>be(e,t).exists((e=>parseInt(e,10)>1));return e.length>0&&P(e,(e=>t(e,"rowspan")||t(e,"colspan")))?C.some(e):C.none()},Ls=(e,t,o)=>t.length<=1?C.none():Bs(e,o.firstSelectedSelector,o.lastSelectedSelector).map((e=>({bounds:e,cells:t}))),Ws="data-mce-selected",Ms="data-mce-first-selected",js="data-mce-last-selected",Ps="["+Ws+"]",Is={selected:Ws,selectedSelector:"td["+Ws+"],th["+Ws+"]",firstSelected:Ms,firstSelectedSelector:"td["+Ms+"],th["+Ms+"]",lastSelected:js,lastSelectedSelector:"td["+js+"],th["+js+"]"},Fs=(e,t,o)=>({element:o,mergable:Ls(t,e,Is),unmergable:As(e),selection:zs(e)}),Hs=e=>(t,o)=>{const n=ne(t),r="col"===n||"colgroup"===n?Gt(s=t).bind((e=>_s(e,Is.firstSelectedSelector))).fold(g(s),(e=>e[0])):t;var s;return wt(r,e,o)},$s=Hs("th,td,caption"),Vs=Hs("th,td"),qs=e=>{return t=e.model.table.getSelectedCells(),E(t,xe.fromDom);var t},Us=(e,t)=>{e.on("BeforeGetContent",(t=>{const o=o=>{t.preventDefault(),(e=>Gt(e[0]).map((e=>{const t=((e,t)=>{const o=e=>Ce(e.element,t),n=Ye(e),r=Xt(n),s=mr(e),l=Zo(r),a=((e,t)=>{const o=e.grid.columns;let n=e.grid.rows,r=o,s=0,l=0;const a=[],c=[];return G(e.access,(e=>{if(a.push(e),t(e)){c.push(e);const t=e.row,o=t+e.rowspan-1,a=e.column,i=a+e.colspan-1;ts&&(s=o),al&&(l=i)}})),((e,t,o,n,r,s)=>({minRow:e,minCol:t,maxRow:o,maxCol:n,allCells:r,selectedCells:s}))(n,r,s,l,a,c)})(l,o),c="th:not("+t+"),td:not("+t+")",i=$t(n,"th,td",(e=>Ce(e,c)));N(i,qe),((e,t,o,n)=>{const r=B(e,(e=>"colgroup"!==e.section)),s=t.grid.columns,l=t.grid.rows;for(let e=0;eo.maxRow||ao.maxCol||(en(t,e,a).filter(n).isNone()?fr(r,l,e):l=!0)}})(r,l,a,o);const m=((e,t,o,n)=>{if(0===n.minCol&&t.grid.columns===n.maxCol+1)return 0;const r=sr(t,e,o),s=A(r,((e,t)=>e+t),0),l=A(r.slice(n.minCol,n.maxCol+1),((e,t)=>e+t),0),a=l/s*o.pixelWidth()-o.pixelWidth();return o.getCellDelta(a)})(e,Xo(e),s,a);return((e,t,o,n)=>{G(o.columns,(e=>{(e.columnt.maxCol)&&qe(e.element)}));const r=B(Ht(e,"tr"),(e=>0===e.dom.childElementCount));N(r,qe),t.minCol!==t.maxCol&&t.minRow!==t.maxRow||N(Ht(e,"th,td"),(e=>{we(e,"rowspan"),we(e,"colspan")})),we(e,Uo),we(e,"data-snooker-col-series"),mr(e).adjustTableWidth(n)})(n,a,l,m),n})(e,Ps);return rs(t),[t]})))(o).each((o=>{const n="text"===t.format?((e,t)=>{const o=e.getDoc(),n=nt(xe.fromDom(e.getBody())),r=xe.fromTag("div",o);ge(r,"data-mce-bogus","all"),_t(r,{position:"fixed",left:"-9999999px",top:"0",overflow:"hidden",opacity:"0"});const s=(e=>ot(e)?e:xe.fromDom(Ee(e).dom.body))(n);$e(r,t),Ie(s,r);const l=r.dom.innerText;return qe(r),l})(e,o):((e,t)=>E(t,(t=>e.selection.serializer.serialize(t.dom,{}))).join(""))(e,o);t.content=n}))};if(!0===t.selection){const t=(e=>B(qs(e),(e=>Ce(e,Is.selectedSelector))))(e);t.length>=1&&o(t)}})),e.on("BeforeSetContent",(o=>{if(!0===o.selection&&!0===o.paste){const n=qs(e);H(n).each((n=>{Gt(n).each((r=>{const s=B((e=>{const t=document.createElement("div");return t.innerHTML=e,Le(xe.fromDom(t))})(o.content),(e=>"meta"!==ne(e))),l=ue("table");if(Gr(e)&&1===s.length&&l(s[0])){o.preventDefault();const l=xe.fromDom(e.getDoc()),a=Br(l),c=((e,t,o)=>({element:e,clipboard:t,generators:o}))(n,s[0],a);t.pasteCells(r,c).each((()=>{e.focus()}))}}))}))}}))},Gs=(e,t)=>({element:e,offset:t}),Ks=(e,t,o)=>e.property().isText(t)&&0===e.property().getText(t).trim().length||e.property().isComment(t)?o(t).bind((t=>Ks(e,t,o).orThunk((()=>C.some(t))))):C.none(),Ys=(e,t)=>e.property().isText(t)?e.property().getText(t).length:e.property().children(t).length,Js=(e,t)=>{const o=Ks(e,t,e.query().prevSibling).getOr(t);if(e.property().isText(o))return Gs(o,Ys(e,o));const n=e.property().children(o);return n.length>0?Js(e,n[n.length-1]):Gs(o,Ys(e,o))},Qs=Js,Xs=xs(),Zs=(e,t)=>{if(!jt(e)){const o=(e=>Un(e).bind((e=>{return t=e,o=["fixed","relative","empty"],C.from(Ln.exec(t)).bind((e=>{const t=Number(e[1]),n=e[2];return((e,t)=>O(t,(t=>O(An[t],(t=>e===t)))))(n,o)?C.some({value:t,unit:n}):C.none()}));var t,o})))(e);o.each((o=>{const n=o.value/2;Jn(e,n,o.unit),Jn(t,n,o.unit)}))}},el=e=>E(e,g(0)),tl=(e,t,o,n,r)=>r(e.slice(0,t)).concat(n).concat(r(e.slice(o))),ol=e=>(t,o,n,r)=>{if(e(n)){const e=Math.max(r,t[o]-Math.abs(n)),s=Math.abs(e-t[o]);return n>=0?s:-s}return n},nl=ol((e=>e<0)),rl=ol(x),sl=()=>{const e=(e,t,o,n)=>{const r=(100+o)/100,s=Math.max(n,(e[t]+o)/r);return E(e,((e,o)=>(o===t?s:e/r)-e))},t=(t,o,n,r,s,l)=>l?e(t,o,r,s):((e,t,o,n,r)=>{const s=nl(e,t,n,r);return tl(e,t,o+1,[s,0],el)})(t,o,n,r,s);return{resizeTable:(e,t)=>e(t),clampTableDelta:nl,calcLeftEdgeDeltas:t,calcMiddleDeltas:(e,o,n,r,s,l,a)=>t(e,n,r,s,l,a),calcRightEdgeDeltas:(t,o,n,r,s,l)=>{if(l)return e(t,n,r,s);{const e=nl(t,n,r,s);return el(t.slice(0,n)).concat([e])}},calcRedestributedWidths:(e,t,o,n)=>{if(n){const n=(t+o)/t,r=E(e,(e=>e/n));return{delta:100*n-100,newSizes:r}}return{delta:o,newSizes:e}}}},ll=()=>{const e=(e,t,o,n,r)=>{const s=rl(e,n>=0?o:t,n,r);return tl(e,t,o+1,[s,-s],el)};return{resizeTable:(e,t,o)=>{o&&e(t)},clampTableDelta:(e,t,o,n,r)=>{if(r){if(o>=0)return o;{const t=A(e,((e,t)=>e+t-n),0);return Math.max(-t,o)}}return nl(e,t,o,n)},calcLeftEdgeDeltas:e,calcMiddleDeltas:(t,o,n,r,s,l)=>e(t,n,r,s,l),calcRightEdgeDeltas:(e,t,o,n,r,s)=>{if(s)return el(e);{const t=n/e.length;return E(e,g(t))}},calcRedestributedWidths:(e,t,o,n)=>({delta:0,newSizes:e})}},al=e=>Xo(e).grid,cl=ue("th"),il=e=>P(e,(e=>cl(e.element))),ml=(e,t)=>e&&t?"sectionCells":e?"section":"cells",dl=e=>{const t="thead"===e.section,o=vt(ul(e.cells),"th");return"tfoot"===e.section?{type:"footer"}:t||o?{type:"header",subType:ml(t,o)}:{type:"body"}},ul=e=>{const t=B(e,(e=>cl(e.element)));return 0===t.length?C.some("td"):t.length===e.length?C.some("th"):C.none()},fl=(e,t,o)=>et(o(e.element,t),!0,e.isLocked),gl=(e,t)=>e.section!==t?tt(e.element,e.cells,t,e.isNew):e,hl=()=>({transformRow:gl,transformCell:(e,t,o)=>{const n=o(e.element,t),r="td"!==ne(n)?(e=>{const t=Je(e,"td");je(e,t);const o=Le(e);return $e(t,o),qe(e),t})(n):n;return et(r,e.isNew,e.isLocked)}}),pl=()=>({transformRow:gl,transformCell:fl}),bl=()=>({transformRow:(e,t)=>gl(e,"thead"===t?"tbody":t),transformCell:fl}),wl=hl,vl=pl,yl=bl,xl=()=>({transformRow:h,transformCell:fl}),Cl=(e,t,o,n)=>{o===n?we(e,t):ge(e,t,o)},Sl=(e,t,o)=>{$(mt(e,t)).fold((()=>Pe(e,o)),(e=>je(e,o)))},Tl=(e,t)=>{const o=[],n=[],r=e=>E(e,(e=>{e.isNew&&o.push(e.element);const t=e.element;return Ve(t),N(e.cells,(e=>{e.isNew&&n.push(e.element),Cl(e.element,"colspan",e.colspan,1),Cl(e.element,"rowspan",e.rowspan,1),Ie(t,e.element)})),t})),s=e=>j(e,(e=>E(e.cells,(e=>(Cl(e.element,"span",e.colspan,1),e.element))))),l=(t,o)=>{const n=((e,t)=>{const o=pt(e,t).getOrThunk((()=>{const o=xe.fromTag(t,ke(e).dom);return"thead"===t?Sl(e,"caption,colgroup",o):"colgroup"===t?Sl(e,"caption",o):Ie(e,o),o}));return Ve(o),o})(e,o),l=("colgroup"===o?s:r)(t);$e(n,l)},a=(t,o)=>{t.length>0?l(t,o):(t=>{pt(e,t).each(qe)})(o)},c=[],i=[],m=[],d=[];return N(t,(e=>{switch(e.section){case"thead":c.push(e);break;case"tbody":i.push(e);break;case"tfoot":m.push(e);break;case"colgroup":d.push(e)}})),a(d,"colgroup"),a(c,"thead"),a(i,"tbody"),a(m,"tfoot"),{newRows:o,newCells:n}},Rl=(e,t)=>{if(0===e.length)return 0;const o=e[0];return W(e,(e=>!t(o.element,e.element))).getOr(e.length)},Dl=(e,t)=>{const o=E(e,(e=>E(e.cells,y)));return E(e,((n,r)=>{const s=j(n.cells,((n,s)=>{if(!1===o[r][s]){const m=((e,t,o,n)=>{const r=((e,t)=>e[t])(e,t),s="colgroup"===r.section,l=Rl(r.cells.slice(o),n),a=s?1:Rl(((e,t)=>E(e,(e=>Fo(e,t))))(e.slice(t),o),n);return{colspan:l,rowspan:a}})(e,r,s,t);return((e,t,n,r)=>{for(let s=e;s({element:e,cells:t,section:o,isNew:n}))(n.element,s,n.section,n.isNew)}))},Ol=(e,t,o)=>{const n=[];N(e.colgroups,(r=>{const s=[];for(let n=0;net(e.element,o,!1))).getOrThunk((()=>et(t.colGap(),!0,!1)));s.push(r)}n.push(tt(r.element,s,"colgroup",o))}));for(let r=0;ret(e.element,o,e.isLocked))).getOrThunk((()=>et(t.gap(),!0,!1)));s.push(l)}const l=e.all[r],a=tt(l.element,s,l.section,o);n.push(a)}return n},kl=e=>Dl(e,Re),El=(e,t)=>V(e.all,(e=>L(e.cells,(e=>Re(t,e.element))))),Nl=(e,t,o)=>{const n=E(t.selection,(t=>Vt(t).bind((t=>El(e,t))).filter(o))),r=yt(n);return xt(r.length>0,r)},_l=(e,t,o,n,r)=>(s,l,a,c)=>{const i=Xo(s),m=C.from(null==c?void 0:c.section).getOrThunk(xl);return t(i,l).map((t=>{const o=((e,t)=>Ol(e,t,!1))(i,a),n=e(o,t,Re,r(a),m),s=Ko(n.grid);return{info:t,grid:kl(n.grid),cursor:n.cursor,lockedColumns:s}})).bind((e=>{const t=Tl(s,e.grid),r=C.from(null==c?void 0:c.sizing).getOrThunk((()=>mr(s))),l=C.from(null==c?void 0:c.resize).getOrThunk(ll);return o(s,e.grid,e.info,{sizing:r,resize:l,section:m}),n(s),we(s,Uo),e.lockedColumns.length>0&&ge(s,Uo,e.lockedColumns.join(",")),C.some({cursor:e.cursor,newRows:t.newRows,newCells:t.newCells})}))},Bl=(e,t)=>Nl(e,t,x).map((e=>({cells:e,generators:t.generators,clipboard:t.clipboard}))),zl=(e,t)=>Nl(e,t,x),Al=(e,t)=>Nl(e,t,(e=>!e.isLocked)),Ll=(e,t)=>P(t,(t=>((e,t)=>El(e,t).exists((e=>!e.isLocked)))(e,t))),Wl=(e,t,o,n)=>{const r=Vo(e).rows;let s=!0;for(let e=0;e{const t=t=>t(e),o=g(e),n=()=>r,r={tag:!0,inner:e,fold:(t,o)=>o(e),isValue:x,isError:y,map:t=>Pl.value(t(e)),mapError:n,bind:t,exists:t,forall:t,getOr:o,or:n,getOrThunk:o,orThunk:n,getOrDie:o,each:t=>{t(e)},toOptional:()=>C.some(e)};return r},jl=e=>{const t=()=>o,o={tag:!1,inner:e,fold:(t,o)=>t(e),isValue:y,isError:x,map:t,mapError:t=>Pl.error(t(e)),bind:t,exists:y,forall:x,getOr:h,or:h,getOrThunk:v,orThunk:v,getOrDie:(n=String(e),()=>{throw new Error(n)}),each:f,toOptional:C.none};var n;return o},Pl={value:Ml,error:jl,fromOption:(e,t)=>e.fold((()=>jl(t)),Ml)},Il=(e,t)=>({rowDelta:0,colDelta:$o(e[0])-$o(t[0])}),Fl=(e,t)=>({rowDelta:e.length-t.length,colDelta:0}),Hl=(e,t,o,n)=>{const r="colgroup"===t.section?o.col:o.cell;return k(e,(e=>et(r(),!0,n(e))))},$l=(e,t,o,n)=>{const r=e[e.length-1];return e.concat(k(t,(()=>{const e="colgroup"===r.section?o.colgroup:o.row,t=qo(r,e,h),s=Hl(t.cells.length,t,o,(e=>X(n,e.toString())));return Io(t,s)})))},Vl=(e,t,o,n)=>E(e,(e=>{const r=Hl(t,e,o,y);return Mo(e,n,r)})),ql=(e,t,o)=>{const n=t.colDelta<0?Vl:h,r=t.rowDelta<0?$l:h,s=Ko(e),l=$o(e[0]),a=O(s,(e=>e===l-1)),c=n(e,Math.abs(t.colDelta),o,a?l-1:l),i=Ko(c);return r(c,Math.abs(t.rowDelta),o,I(i,x))},Ul=(e,t,o,n)=>{const r=b(n,Fo(e[t],o).element),s=e[t];return e.length>1&&$o(s)>1&&(o>0&&r(Ho(s,o-1))||o0&&r(Ho(e[t-1],o))||tB(o,(o=>o>=e.column&&o<=$o(t[0])+e.column)),Kl=(e,t,o,n,r)=>{((e,t,o,n)=>{t>0&&t{const r=e.cells[t-1];let s=0;const l=n();for(;e.cells.length>t+s&&o(r.element,e.cells[t+s].element);)Po(e,t+s,et(l,!0,e.cells[t+s].isLocked)),s++}))})(t,e,r,n.cell);const s=Fl(o,t),l=ql(o,s,n),a=Fl(t,l),c=ql(t,a,n);return E(c,((t,o)=>Mo(t,e,l[o].cells)))},Yl=(e,t,o,n,r)=>{((e,t,o,n)=>{const r=Vo(e).rows;if(t>0&&tA(e,((e,o)=>O(e,(e=>t(e.element,o.element)))?e:e.concat([o])),[]))(r[t-1].cells,o);N(e,(e=>{let s=C.none();for(let l=t;l{Po(a,t,et(e,!0,c.isLocked))})))}}))}})(t,e,r,n.cell);const s=Ko(t),l=Il(t,o),a={...l,colDelta:l.colDelta-s.length},c=ql(t,a,n),{cols:i,rows:m}=Vo(c),d=Ko(c),u=Il(o,t),f={...u,colDelta:u.colDelta+d.length},g=(p=n,b=d,E(o,(e=>A(b,((t,o)=>{const n=Hl(1,e,p,x)[0];return jo(t,o,n)}),e)))),h=ql(g,f,n);var p,b;return[...i,...m.slice(0,e),...h,...m.slice(e,m.length)]},Jl=(e,t,o,n,r)=>{const{rows:s,cols:l}=Vo(e),a=s.slice(0,t),c=s.slice(t);return[...l,...a,((e,t,o,n)=>qo(e,(e=>n(e,o)),t))(s[o],((e,o)=>t>0&&tE(e,(e=>{const s=t>0&&t<$o(e)&&n(Ho(e,t-1),Ho(e,t)),l=((e,t,o,n,r,s,l)=>{if("colgroup"!==o&&n)return Fo(e,t);{const t=Fo(e,r);return et(l(t.element,s),!0,!1)}})(e,t,e.section,s,o,n,r);return jo(e,t,l)})),Xl=(e,t,o,n)=>((e,t,o,n)=>void 0!==Ho(e[t],o)&&t>0&&n(Ho(e[t-1],o),Ho(e[t],o)))(e,t,o,n)||((e,t,o)=>t>0&&o(Ho(e,t-1),Ho(e,t)))(e[t],o,n),Zl=(e,t,o,n)=>{const r=e=>(e=>"row"===e?(e=>Mt(e,"rowspan")>1)(t):jt(t))(e)?`${e}group`:e;return e?cl(t)?r(o):null:n&&cl(t)?r("row"===o?"col":"row"):null},ea=(e,t,o)=>et(o(e.element,t),!0,e.isLocked),ta=(e,t,o,n,r,s,l)=>E(e,((e,a)=>(e=>{const c=e.cells,i=E(c,((e,c)=>{if((e=>O(t,(t=>o(e.element,t.element))))(e)){const t=l(e,a,c)?r(e,o,n):e;return s(t,a,c).each((e=>{var o,n;o=t.element,n={scope:C.from(e)},G(n,((e,t)=>{e.fold((()=>{we(o,t)}),(e=>{fe(o.dom,t,e)}))}))})),t}return e}));return tt(e.element,i,e.section,e.isNew)})(e))),oa=(e,t,o)=>j(e,((n,r)=>Xl(e,r,t,o)?[]:[Fo(n,t)])),na=(e,t,o,n,r)=>{const s=Vo(e).rows,l=j(t,(e=>oa(s,e,n))),a=E(s,(e=>il(e.cells))),c=((e,t)=>P(t,h)&&il(e)?x:(e,o,n)=>!("th"===ne(e.element)&&t[o]))(l,a),i=((e,t)=>(o,n)=>C.some(Zl(e,o.element,"row",t[n])))(o,a);return ta(e,l,n,r,ea,i,c)},ra=(e,t,o,n)=>{const r=Vo(e).rows,s=E(t,(e=>Fo(r[e.row],e.column)));return ta(e,s,o,n,ea,C.none,x)},sa=e=>{if(!l(e))throw new Error("cases must be an array");if(0===e.length)throw new Error("there must be at least one case");const t=[],o={};return N(e,((n,r)=>{const s=q(n);if(1!==s.length)throw new Error("one and only one name per case");const a=s[0],c=n[a];if(void 0!==o[a])throw new Error("duplicate key detected:"+a);if("cata"===a)throw new Error("cannot have a case named cata (sorry)");if(!l(c))throw new Error("case arguments must be an array");t.push(a),o[a]=(...o)=>{const n=o.length;if(n!==c.length)throw new Error("Wrong number of arguments to case "+a+". Expected "+c.length+" ("+c+"), got "+n);return{fold:(...t)=>{if(t.length!==e.length)throw new Error("Wrong number of arguments to fold. Expected "+e.length+", got "+t.length);return t[r].apply(null,o)},match:e=>{const n=q(e);if(t.length!==n.length)throw new Error("Wrong number of arguments to match. Expected: "+t.join(",")+"\nActual: "+n.join(","));if(!P(t,(e=>D(n,e))))throw new Error("Not all branches were specified when using match. Specified: "+n.join(", ")+"\nRequired: "+t.join(", "));return e[a].apply(null,o)},log:e=>{console.log(e,{constructors:t,constructor:a,params:o})}}}})),o},la={...sa([{none:[]},{only:["index"]},{left:["index","next"]},{middle:["prev","index","next"]},{right:["prev","index"]}])},aa=(e,t,o)=>{const n=((e,t)=>sn(e)?((e,t)=>{const o=rn(e);return E(o,((e,o)=>({element:e.element,width:t[o],colspan:e.colspan})))})(e,t):((e,t)=>{const o=nn(e);return E(o,(e=>{const o=((e,t,o)=>{let n=0;for(let r=e;r{o.setElementWidth(e.element,e.width)}))},ca=(e,t,o,n,r)=>{const s=Xo(e),l=r.getCellDelta(t),a=r.getWidths(s,r),c=o===s.grid.columns-1,i=n.clampTableDelta(a,o,l,r.minCellWidth(),c),m=((e,t,o,n,r)=>{const s=e.slice(0),l=((e,t)=>0===e.length?la.none():1===e.length?la.only(0):0===t?la.left(0,1):t===e.length-1?la.right(t-1,t):t>0&&tn.singleColumnWidth(s[e],o)),((e,t)=>r.calcLeftEdgeDeltas(s,e,t,o,n.minCellWidth(),n.isRelative)),((e,t,l)=>r.calcMiddleDeltas(s,e,t,l,o,n.minCellWidth(),n.isRelative)),((e,t)=>r.calcRightEdgeDeltas(s,e,t,o,n.minCellWidth(),n.isRelative)))})(a,o,i,r,n),d=E(m,((e,t)=>e+a[t]));aa(s,d,r),n.resizeTable(r.adjustTableWidth,i,c)},ia=(e,t,o)=>{const n=Xo(e),r=((e,t)=>lr(e,t,Yn,(e=>e.getOrThunk(Ft))))(n,e),s=E(r,((e,n)=>o===n?Math.max(t+e,Ft()):e)),l=((e,t)=>E(e.all,((e,o)=>({element:e.element,height:t[o]}))))(n,s);N(l,(e=>{$n(e.element,e.height)})),N(nn(n),(e=>{(e=>{Lt(e,"height")})(e.element)}));const a=z(s,((e,t)=>e+t),0);$n(e,a)},ma=e=>A(e,((e,t)=>O(e,(e=>e.column===t.column))?e:e.concat([t])),[]).sort(((e,t)=>e.column-t.column)),da=ue("col"),ua=ue("colgroup"),fa=e=>"tr"===ne(e)||ua(e),ga=e=>({element:e,colspan:Wt(e,"colspan",1),rowspan:Wt(e,"rowspan",1)}),ha=e=>be(e,"scope").map((e=>e.substr(0,3))),pa=(e,t=ga)=>{const o=o=>{if(fa(o))return ua((r={element:o}).element)?e.colgroup(r):e.row(r);{const r=o,s=(t=>da(t.element)?e.col(t):e.cell(t))(t(r));return n=C.some({item:r,replacement:s}),s}var r};let n=C.none();return{getOrInit:(e,t)=>n.fold((()=>o(e)),(n=>t(e,n.item)?n.replacement:o(e)))}},ba=e=>t=>{const o=[],n=n=>{const r="td"===e?{scope:null}:{},s=t.replace(n,e,r);return o.push({item:n,sub:s}),s};return{replaceOrInit:(e,t)=>{if(fa(e)||da(e))return e;{const r=e;return((e,t)=>L(o,(o=>t(o.item,e))))(r,t).fold((()=>n(r)),(o=>t(e,o.item)?o.sub:n(r)))}}}},wa=e=>({unmerge:t=>{const o=ha(t);return o.each((e=>ge(t,"scope",e))),()=>{const n=e.cell({element:t,colspan:1,rowspan:1});return Lt(n,"width"),Lt(t,"width"),o.each((e=>ge(n,"scope",e))),n}},merge:e=>(Lt(e[0],"width"),(()=>{const t=yt(E(e,ha));if(0===t.length)return C.none();{const e=t[0],o=["row","col"];return O(t,(t=>t!==e&&D(o,t)))?C.none():C.from(e)}})().fold((()=>we(e[0],"scope")),(t=>ge(e[0],"scope",t+"group"))),g(e[0]))}),va=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","table","thead","tfoot","tbody","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"],ya=xs(),xa=e=>((e,t)=>{const o=e.property().name(t);return D(va,o)})(ya,e),Ca=e=>((e,t)=>{const o=e.property().name(t);return D(["ol","ul"],o)})(ya,e),Sa=e=>{const t=ue("br"),o=e=>Cr(e).bind((o=>{const n=Ae(o).map((e=>!!xa(e)||!!((e,t)=>D(["br","img","hr","input"],e.property().name(t)))(ya,e)&&"img"!==ne(e))).getOr(!1);return Ne(o).map((r=>{return!0===n||("li"===ne(s=r)||ft(s,Ca).isSome())||t(o)||xa(r)&&!Re(e,r)?[]:[xe.fromTag("br")];var s}))})).getOr([]),n=(()=>{const n=j(e,(e=>{const n=Le(e);return(e=>P(e,(e=>t(e)||ie(e)&&0===hr(e).trim().length)))(n)?[]:n.concat(o(e))}));return 0===n.length?[xe.fromTag("br")]:n})();Ve(e[0]),$e(e[0],n)},Ta=e=>es(e,!0),Ra=e=>{0===qt(e).length&&qe(e)},Da=(e,t)=>({grid:e,cursor:t}),Oa=(e,t,o)=>{const n=((e,t,o)=>{var n,r;const s=Vo(e).rows;return C.from(null===(r=null===(n=s[t])||void 0===n?void 0:n.cells[o])||void 0===r?void 0:r.element).filter(Ta).orThunk((()=>(e=>V(e,(e=>V(e.cells,(e=>{const t=e.element;return xt(Ta(t),t)})))))(s)))})(e,t,o);return Da(e,n)},ka=e=>A(e,((e,t)=>O(e,(e=>e.row===t.row))?e:e.concat([t])),[]).sort(((e,t)=>e.row-t.row)),Ea=(e,t)=>(o,n,r,s,l)=>{const a=ka(n),c=E(a,(e=>e.row)),i=((e,t,o,n,r,s,l)=>{const{cols:a,rows:c}=Vo(e),i=c[t[0]],m=j(t,(e=>((e,t,o)=>{const n=e[t];return j(n.cells,((n,r)=>Xl(e,t,r,o)?[]:[n]))})(c,e,r))),d=E(i.cells,((e,t)=>il(oa(c,t,r)))),u=[...c];N(t,(e=>{u[e]=l.transformRow(c[e],o)}));const f=[...a,...u],g=((e,t)=>P(t,h)&&il(e.cells)?x:(e,o,n)=>!("th"===ne(e.element)&&t[n]))(i,d),p=((e,t)=>(o,n,r)=>C.some(Zl(e,o.element,"col",t[r])))(n,d);return ta(f,m,r,s,l.transformCell,p,g)})(o,c,e,t,r,s.replaceOrInit,l);return Oa(i,n[0].row,n[0].column)},Na=Ea("thead",!0),_a=Ea("tbody",!1),Ba=Ea("tfoot",!1),za=(e,t,o)=>{const n=((e,t)=>Jt(e,(()=>t)))(e,o.section),r=Zo(n);return Ol(r,t,!0)},Aa=(e,t,o,n)=>((e,t,o,n)=>{const r=Zo(t),s=n.getWidths(r,n);aa(r,s,n)})(0,t,0,n.sizing),La=(e,t,o,n)=>((e,t,o,n,r)=>{const s=Zo(t),l=n.getWidths(s,n),a=n.pixelWidth(),{newSizes:c,delta:i}=r.calcRedestributedWidths(l,a,o.pixelDelta,n.isRelative);aa(s,c,n),n.adjustTableWidth(i)})(0,t,o,n.sizing,n.resize),Wa=(e,t)=>O(t,(e=>0===e.column&&e.isLocked)),Ma=(e,t)=>O(t,(t=>t.column+t.colspan>=e.grid.columns&&t.isLocked)),ja=(e,t)=>{const o=an(e),n=ma(t);return A(n,((e,t)=>e+o[t.column].map(Lo).getOr(0)),0)},Pa=e=>(t,o)=>zl(t,o).filter((o=>!(e?Wa:Ma)(t,o))).map((e=>({details:e,pixelDelta:ja(t,e)}))),Ia=e=>(t,o)=>Bl(t,o).filter((o=>!(e?Wa:Ma)(t,o.cells))),Fa=ba("th"),Ha=ba("td"),$a=_l(((e,t,o,n)=>{const r=t[0].row,s=ka(t),l=z(s,((e,t)=>({grid:Jl(e.grid,r,t.row+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return Oa(l,r,t[0].column)}),zl,f,f,pa),Va=_l(((e,t,o,n)=>{const r=ka(t),s=r[r.length-1],l=s.row+s.rowspan,a=z(r,((e,t)=>Jl(e,l,t.row,o,n.getOrInit)),e);return Oa(a,l,t[0].column)}),zl,f,f,pa),qa=_l(((e,t,o,n)=>{const r=t.details,s=ma(r),l=s[0].column,a=z(s,((e,t)=>({grid:Ql(e.grid,l,t.column+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return Oa(a,r[0].row,l)}),Pa(!0),La,f,pa),Ua=_l(((e,t,o,n)=>{const r=t.details,s=r[r.length-1],l=s.column+s.colspan,a=ma(r),c=z(a,((e,t)=>Ql(e,l,t.column,o,n.getOrInit)),e);return Oa(c,r[0].row,l)}),Pa(!1),La,f,pa),Ga=_l(((e,t,o,n)=>{const r=ma(t.details),s=((e,t)=>j(e,(e=>{const o=e.cells,n=z(t,((e,t)=>t>=0&&t0?[tt(e.element,n,e.section,e.isNew)]:[]})))(e,E(r,(e=>e.column))),l=s.length>0?s[0].cells.length-1:0;return Oa(s,r[0].row,Math.min(r[0].column,l))}),((e,t)=>Al(e,t).map((t=>({details:t,pixelDelta:-ja(e,t)})))),La,Ra,pa),Ka=_l(((e,t,o,n)=>{const r=ka(t),s=((e,t,o)=>{const{rows:n,cols:r}=Vo(e);return[...r,...n.slice(0,t),...n.slice(o+1)]})(e,r[0].row,r[r.length-1].row),l=Math.max(Vo(s).rows.length-1,0);return Oa(s,Math.min(t[0].row,l),t[0].column)}),zl,f,Ra,pa),Ya=_l(((e,t,o,n)=>{const r=ma(t),s=E(r,(e=>e.column)),l=na(e,s,!0,o,n.replaceOrInit);return Oa(l,t[0].row,t[0].column)}),Al,f,f,Fa),Ja=_l(((e,t,o,n)=>{const r=ma(t),s=E(r,(e=>e.column)),l=na(e,s,!1,o,n.replaceOrInit);return Oa(l,t[0].row,t[0].column)}),Al,f,f,Ha),Qa=_l(Na,zl,f,f,Fa),Xa=_l(_a,zl,f,f,Ha),Za=_l(Ba,zl,f,f,Ha),ec=_l(((e,t,o,n)=>{const r=ra(e,t,o,n.replaceOrInit);return Oa(r,t[0].row,t[0].column)}),Al,f,f,Fa),tc=_l(((e,t,o,n)=>{const r=ra(e,t,o,n.replaceOrInit);return Oa(r,t[0].row,t[0].column)}),Al,f,f,Ha),oc=_l(((e,t,o,n)=>{const r=t.cells;Sa(r);const s=((e,t,o,n)=>{const r=Vo(e).rows;if(0===r.length)return e;for(let e=t.startRow;e<=t.finishRow;e++)for(let o=t.startCol;o<=t.finishCol;o++){const t=r[e],s=Fo(t,o).isLocked;Po(t,o,et(n(),!1,s))}return e})(e,t.bounds,0,n.merge(r));return Da(s,C.from(r[0]))}),((e,t)=>((e,t)=>t.mergable)(0,t).filter((t=>Ll(e,t.cells)))),Aa,f,wa),nc=_l(((e,t,o,n)=>{const r=z(t,((e,t)=>Wl(e,t,o,n.unmerge(t))),e);return Da(r,C.from(t[0]))}),((e,t)=>((e,t)=>t.unmergable)(0,t).filter((t=>Ll(e,t)))),Aa,f,wa),rc=_l(((e,t,o,n)=>{const r=((e,t)=>{const o=Xo(e);return Ol(o,t,!0)})(t.clipboard,t.generators);var s,l;return((e,t,o,n,r)=>{const s=Ko(t),l=((e,t,o)=>{const n=$o(t[0]),r=Vo(t).cols.length+e.row,s=k(n-e.column,(t=>t+e.column));return{row:r,column:L(s,(e=>P(o,(t=>t!==e)))).getOr(n-1)}})(e,t,s),a=Vo(o).rows,c=Gl(l,a,s),i=((e,t,o)=>{if(e.row>=t.length||e.column>$o(t[0]))return Pl.error("invalid start address out of table bounds, row: "+e.row+", column: "+e.column);const n=t.slice(e.row),r=n[0].cells.slice(e.column),s=$o(o[0]),l=o.length;return Pl.value({rowDelta:n.length-l,colDelta:r.length-s})})(l,t,a);return i.map((e=>{const o={...e,colDelta:e.colDelta-c.length},s=ql(t,o,n),i=Ko(s),m=Gl(l,a,i);return((e,t,o,n,r,s)=>{const l=e.row,a=e.column,c=l+o.length,i=a+$o(o[0])+s.length,m=I(s,x);for(let e=l;eDa(e,C.some(t.element))),(e=>Oa(e,t.row,t.column)))}),((e,t)=>Vt(t.element).bind((o=>El(e,o).map((e=>({...e,generators:t.generators,clipboard:t.clipboard})))))),Aa,f,pa),sc=_l(((e,t,o,n)=>{const r=Vo(e).rows,s=t.cells[0].column,l=r[t.cells[0].row],a=za(t.clipboard,t.generators,l),c=Kl(s,e,a,t.generators,o);return Oa(c,t.cells[0].row,t.cells[0].column)}),Ia(!0),f,f,pa),lc=_l(((e,t,o,n)=>{const r=Vo(e).rows,s=t.cells[t.cells.length-1].column+t.cells[t.cells.length-1].colspan,l=r[t.cells[0].row],a=za(t.clipboard,t.generators,l),c=Kl(s,e,a,t.generators,o);return Oa(c,t.cells[0].row,s)}),Ia(!1),f,f,pa),ac=_l(((e,t,o,n)=>{const r=Vo(e).rows,s=t.cells[0].row,l=r[s],a=za(t.clipboard,t.generators,l),c=Yl(s,e,a,t.generators,o);return Oa(c,t.cells[0].row,t.cells[0].column)}),Bl,f,f,pa),cc=_l(((e,t,o,n)=>{const r=Vo(e).rows,s=t.cells[t.cells.length-1].row+t.cells[t.cells.length-1].rowspan,l=r[t.cells[0].row],a=za(t.clipboard,t.generators,l),c=Yl(s,e,a,t.generators,o);return Oa(c,s,t.cells[0].column)}),Bl,f,f,pa),ic=(e,t)=>{const o=Xo(e);return zl(o,t).bind((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=M(E(o.all,(e=>B(e.cells,(e=>e.column>=n&&e.column{const o=Xo(e);return zl(o,t).bind(ul).getOr("")},dc=(e,t)=>{const o=Xo(e);return zl(o,t).bind((e=>{const t=e[e.length-1],n=e[0].row,r=t.row+t.rowspan;return(e=>{const t=E(e,(e=>dl(e).type)),o=D(t,"header"),n=D(t,"footer");if(o||n){const e=D(t,"body");return!o||e||n?o||e||!n?C.none():C.some("footer"):C.some("header")}return C.some("body")})(o.all.slice(n,r))})).getOr("")},uc=(e,t)=>e.dispatch("NewRow",{node:t}),fc=(e,t)=>e.dispatch("NewCell",{node:t}),gc=(e,t,o)=>{e.dispatch("TableModified",{...o,table:t})},hc={structure:!1,style:!0},pc={structure:!0,style:!1},bc={structure:!0,style:!0},wc=(e,t)=>Hr(e)?ur(t):$r(e)?dr(t):mr(t),vc=(e,t,o)=>{const n=e=>"table"===ne(os(e)),r=Wr(e),s=Ir(e)?f:Zs,l=t=>{switch(Mr(e)){case"section":return wl();case"sectionCells":return vl();case"cells":return yl();default:return((e,t)=>{var o;switch((o=Xo(e),V(o.all,(e=>{const t=dl(e);return"header"===t.type?C.from(t.subType):C.none()}))).getOr(t)){case"section":return hl();case"sectionCells":return pl();case"cells":return bl()}})(t,"section")}},a=(n,s,a,c)=>(i,m,d=!1)=>{rs(i);const u=xe.fromDom(e.getDoc()),f=_r(a,u,r),g={sizing:wc(e,i),resize:Ir(e)?sl():ll(),section:l(i)};return s(i)?n(i,m,f,g).bind((n=>{t.refresh(i.dom),N(n.newRows,(t=>{uc(e,t.dom)})),N(n.newCells,(t=>{fc(e,t.dom)}));const r=((t,n)=>n.cursor.fold((()=>{const n=qt(t);return H(n).filter(st).map((n=>{o.clearSelectedCells(t.dom);const r=e.dom.createRng();return r.selectNode(n.dom),e.selection.setRng(r),ge(n,"data-mce-selected","1"),r}))}),(n=>{const r=Qs(Xs,n),s=e.dom.createRng();return s.setStart(r.element.dom,r.offset),s.setEnd(r.element.dom,r.offset),e.selection.setRng(s),o.clearSelectedCells(t.dom),C.some(s)})))(i,n);return st(i)&&(rs(i),d||gc(e,i.dom,c)),r.map((e=>({rng:e,effect:c})))})):C.none()},c=a(Ka,(t=>!n(e)||al(t).rows>1),f,pc),i=a(Ga,(t=>!n(e)||al(t).columns>1),f,pc);return{deleteRow:c,deleteColumn:i,insertRowsBefore:a($a,x,f,pc),insertRowsAfter:a(Va,x,f,pc),insertColumnsBefore:a(qa,x,s,pc),insertColumnsAfter:a(Ua,x,s,pc),mergeCells:a(oc,x,f,pc),unmergeCells:a(nc,x,f,pc),pasteColsBefore:a(sc,x,f,pc),pasteColsAfter:a(lc,x,f,pc),pasteRowsBefore:a(ac,x,f,pc),pasteRowsAfter:a(cc,x,f,pc),pasteCells:a(rc,x,f,bc),makeCellsHeader:a(ec,x,f,pc),unmakeCellsHeader:a(tc,x,f,pc),makeColumnsHeader:a(Ya,x,f,pc),unmakeColumnsHeader:a(Ja,x,f,pc),makeRowsHeader:a(Qa,x,f,pc),makeRowsBody:a(Xa,x,f,pc),makeRowsFooter:a(Za,x,f,pc),getTableRowType:dc,getTableCellType:mc,getTableColType:ic}},yc=(e,t,o)=>{const n=Wt(e,t,1);1===o||n<=1?we(e,t):ge(e,t,Math.min(o,n))},xc=(e,t)=>o=>{const n=o.column+o.colspan-1,r=o.column;return n>=e&&r{const n=o.substring(0,o.length-e.length),r=parseFloat(n);return n===r.toString()?t(r):Cc.invalid(o)},Tc={...Cc,from:e=>Rt(e,"%")?Sc("%",Cc.percent,e):Rt(e,"px")?Sc("px",Cc.pixels,e):Cc.invalid(e)},Rc=(e,t,o)=>{const n=Tc.from(o),r=P(e,(e=>"0px"===e))?((e,t)=>{const o=e.fold((()=>g("")),(e=>g(e/t+"px")),(()=>g(100/t+"%")));return k(t,o)})(n,e.length):((e,t,o)=>e.fold((()=>t),(e=>((e,t,o)=>{const n=o/t;return E(e,(e=>Tc.from(e).fold((()=>e),(e=>e*n+"px"),(e=>e/100*o+"px"))))})(t,o,e)),(e=>((e,t)=>E(e,(e=>Tc.from(e).fold((()=>e),(e=>e/t*100+"%"),(e=>e+"%")))))(t,o))))(n,e,t);return kc(r)},Dc=(e,t)=>0===e.length?t:z(e,((e,t)=>Tc.from(t).fold(g(0),h,h)+e),0),Oc=(e,t)=>Tc.from(e).fold(g(e),(e=>e+t+"px"),(e=>e+t+"%")),kc=e=>{if(0===e.length)return e;const t=z(e,((e,t)=>{const o=Tc.from(t).fold((()=>({value:t,remainder:0})),(e=>(e=>{const t=Math.floor(e);return{value:t+"px",remainder:e-t}})(e)),(e=>({value:e+"%",remainder:0})));return{output:[o.value].concat(e.output),remainder:e.remainder+o.remainder}}),{output:[],remainder:0}),o=t.output;return o.slice(0,o.length-1).concat([Oc(o[o.length-1],Math.round(t.remainder))])},Ec=Tc.from,Nc=(e,t,o)=>{const n=Xo(e),r=n.all,s=nn(n),l=rn(n);t.each((t=>{const o=Ec(t).fold(g("px"),g("px"),g("%")),r=Ao(e),a=((e,t)=>nr(e,t,er,rr))(n,e),c=Rc(a,r,t);sn(n)?((e,t,o)=>{N(t,((t,n)=>{const r=Dc([e[n]],It());Nt(t.element,"width",r+o)}))})(c,l,o):((e,t,o)=>{N(t,(t=>{const n=e.slice(t.column,t.colspan+t.column),r=Dc(n,It());Nt(t.element,"width",r+o)}))})(c,s,o),Nt(e,"width",t)})),o.each((t=>{const o=gn(e),l=((e,t)=>lr(e,t,tr,rr))(n,e);((e,t,o)=>{N(o,(e=>{Lt(e.element,"height")})),N(t,((t,o)=>{Nt(t.element,"height",e[o])}))})(Rc(l,o,t),r,s),Nt(e,"height",t)}))},_c=e=>Un(e).exists((e=>Wn.test(e))),Bc=e=>Un(e).exists((e=>Mn.test(e))),zc=e=>Un(e).isNone(),Ac=e=>{we(e,"width"),we(e,"height")},Lc=e=>{const t=Qn(e);Nc(e,C.some(t),C.none()),Ac(e)},Wc=e=>{const t=(e=>Ao(e)+"px")(e);Nc(e,C.some(t),C.none()),Ac(e)},Mc=e=>{Lt(e,"width");const t=Ut(e),o=t.length>0?t:qt(e);N(o,(e=>{Lt(e,"width"),Ac(e)})),Ac(e)},jc={styles:{"border-collapse":"collapse",width:"100%"},attributes:{border:"1"},colGroups:!1},Pc=(e,t,o,n)=>k(e,(e=>((e,t,o,n)=>{const r=xe.fromTag("tr");for(let s=0;s{e.selection.select(t.dom,!0),e.selection.collapse(!0)},Fc=(e,t,o,n,s)=>{const l=(e=>{const t=e.options,o=t.get("table_default_styles");return t.isSet("table_default_styles")?o:((e,t)=>Vr(e)||!Ur(e)?t:$r(e)?{...t,width:Lr(e)}:{...t,width:Ar})(e,o)})(e),a={styles:l,attributes:Kr(e),colGroups:Yr(e)};return e.undoManager.ignore((()=>{const r=((e,t,o,n,r,s=jc)=>{const l=xe.fromTag("table"),a="cells"!==r;_t(l,s.styles),he(l,s.attributes),s.colGroups&&Ie(l,(e=>{const t=xe.fromTag("colgroup");return k(e,(()=>Ie(t,xe.fromTag("col")))),t})(t));const c=Math.min(e,o);if(a&&o>0){const e=xe.fromTag("thead");Ie(l,e);const s=Pc(o,t,"sectionCells"===r?c:0,n);$e(e,s)}const i=xe.fromTag("tbody");Ie(l,i);const m=Pc(a?e-c:e,t,a?0:o,n);return $e(i,m),l})(o,t,s,n,Mr(e),a);ge(r,"data-mce-id","__mce");const l=(e=>{const t=xe.fromTag("div"),o=xe.fromDom(e.dom.cloneNode(!0));return Ie(t,o),(e=>e.dom.innerHTML)(t)})(r);e.insertContent(l),e.addVisual()})),bt(os(e),'table[data-mce-id="__mce"]').map((t=>($r(e)?Wc(t):Vr(e)?Mc(t):(Hr(e)||(e=>r(e)&&-1!==e.indexOf("%"))(l.width))&&Lc(t),rs(t),we(t,"data-mce-id"),((e,t)=>{N(dt(t,"tr"),(t=>{uc(e,t.dom),N(dt(t,"th,td"),(t=>{fc(e,t.dom)}))}))})(e,t),((e,t)=>{bt(t,"td,th").each(b(Ic,e))})(e,t),t.dom))).getOrNull()};var Hc=tinymce.util.Tools.resolve("tinymce.FakeClipboard");const $c="x-tinymce/dom-table-",Vc=$c+"rows",qc=$c+"columns",Uc=e=>{const t=Hc.FakeClipboardItem(e);Hc.write([t])},Gc=e=>{var t;const o=null!==(t=Hc.read())&&void 0!==t?t:[];return V(o,(t=>C.from(t.getType(e))))},Kc=e=>{Gc(e).isSome()&&Hc.clear()},Yc=e=>{e.fold(Qc,(e=>Uc({[Vc]:e})))},Jc=()=>Gc(Vc),Qc=()=>Kc(Vc),Xc=e=>{e.fold(ei,(e=>Uc({[qc]:e})))},Zc=()=>Gc(qc),ei=()=>Kc(qc),ti=e=>$s(ss(e),ns(e)).filter(ds),oi=(e,t)=>{const o=ns(e),n=e=>Gt(e,o),l=t=>(e=>Vs(ss(e),ns(e)).filter(ds))(e).bind((e=>n(e).map((o=>t(o,e))))),a=t=>{e.focus()},c=(t,o=!1)=>l(((n,r)=>{const s=Fs(qs(e),n,r);t(n,s,o).each(a)})),i=()=>l(((t,o)=>((e,t,o)=>{const n=Xo(e);return zl(n,t).bind((e=>{const t=Ol(n,o,!1),r=Vo(t).rows.slice(e[0].row,e[e.length-1].row+e[e.length-1].rowspan),s=j(r,(e=>{const t=B(e.cells,(e=>!e.isLocked));return t.length>0?[{...e,cells:t}]:[]})),l=kl(s);return xt(l.length>0,l)})).map((e=>E(e,(e=>{const t=Ke(e.element);return N(e.cells,(e=>{const o=Ye(e.element);Cl(o,"colspan",e.colspan,1),Cl(o,"rowspan",e.rowspan,1),Ie(t,o)})),t}))))})(t,Fs(qs(e),t,o),_r(f,xe.fromDom(e.getDoc()),C.none())))),m=()=>l(((t,o)=>((e,t)=>{const o=Xo(e);return Al(o,t).map((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=((e,t,o)=>{if(sn(e)){const n=B(rn(e),xc(t,o)),r=E(n,(e=>{const n=Ye(e.element);return yc(n,"span",o-t),n})),s=xe.fromTag("colgroup");return $e(s,r),[s]}return[]})(o,n,r),l=((e,t,o)=>E(e.all,(e=>{const n=B(e.cells,xc(t,o)),r=E(n,(e=>{const n=Ye(e.element);return yc(n,"colspan",o-t),n})),s=xe.fromTag("tr");return $e(s,r),s})))(o,n,r);return[...s,...l]}))})(t,Fs(qs(e),t,o)))),d=(t,o)=>o().each((o=>{const n=E(o,(e=>Ye(e)));l(((o,r)=>{const s=Br(xe.fromDom(e.getDoc())),l=((e,t,o,n)=>({selection:zs(e),clipboard:o,generators:n}))(qs(e),0,n,s);t(o,l).each(a)}))})),g=e=>(t,o)=>((e,t)=>X(e,t)?C.from(e[t]):C.none())(o,"type").each((t=>{c(e(t),o.no_events)}));G({mceTableSplitCells:()=>c(t.unmergeCells),mceTableMergeCells:()=>c(t.mergeCells),mceTableInsertRowBefore:()=>c(t.insertRowsBefore),mceTableInsertRowAfter:()=>c(t.insertRowsAfter),mceTableInsertColBefore:()=>c(t.insertColumnsBefore),mceTableInsertColAfter:()=>c(t.insertColumnsAfter),mceTableDeleteCol:()=>c(t.deleteColumn),mceTableDeleteRow:()=>c(t.deleteRow),mceTableCutCol:()=>m().each((e=>{Xc(e),c(t.deleteColumn)})),mceTableCutRow:()=>i().each((e=>{Yc(e),c(t.deleteRow)})),mceTableCopyCol:()=>m().each((e=>Xc(e))),mceTableCopyRow:()=>i().each((e=>Yc(e))),mceTablePasteColBefore:()=>d(t.pasteColsBefore,Zc),mceTablePasteColAfter:()=>d(t.pasteColsAfter,Zc),mceTablePasteRowBefore:()=>d(t.pasteRowsBefore,Jc),mceTablePasteRowAfter:()=>d(t.pasteRowsAfter,Jc),mceTableDelete:()=>ti(e).each((t=>{Gt(t,o).filter(w(o)).each((t=>{const o=xe.fromText("");if(je(t,o),qe(t),e.dom.isEmpty(e.getBody()))e.setContent(""),e.selection.setCursorLocation();else{const t=e.dom.createRng();t.setStart(o.dom,0),t.setEnd(o.dom,0),e.selection.setRng(t),e.nodeChanged()}}))})),mceTableCellToggleClass:(t,o)=>{l((t=>{const n=qs(e),r=P(n,(t=>e.formatter.match("tablecellclass",{value:o},t.dom))),s=r?e.formatter.remove:e.formatter.apply;N(n,(e=>s("tablecellclass",{value:o},e.dom))),gc(e,t.dom,hc)}))},mceTableToggleClass:(t,o)=>{l((t=>{e.formatter.toggle("tableclass",{value:o},t.dom),gc(e,t.dom,hc)}))},mceTableToggleCaption:()=>{ti(e).each((t=>{Gt(t,o).each((o=>{pt(o,"caption").fold((()=>{const t=xe.fromTag("caption");Ie(t,xe.fromText("Caption")),((e,t)=>{We(e,0).fold((()=>{Ie(e,t)}),(e=>{Me(e,t)}))})(o,t),e.selection.setCursorLocation(t.dom,0)}),(n=>{ue("caption")(t)&&Te("td",o).each((t=>e.selection.setCursorLocation(t.dom,0))),qe(n)})),gc(e,o.dom,pc)}))}))},mceTableSizingMode:(t,n)=>(t=>ti(e).each((n=>{Vr(e)||$r(e)||Hr(e)||Gt(n,o).each((o=>{"relative"!==t||_c(o)?"fixed"!==t||Bc(o)?"responsive"!==t||zc(o)||Mc(o):Wc(o):Lc(o),rs(o),gc(e,o.dom,pc)}))})))(n),mceTableCellType:g((e=>"th"===e?t.makeCellsHeader:t.unmakeCellsHeader)),mceTableColType:g((e=>"th"===e?t.makeColumnsHeader:t.unmakeColumnsHeader)),mceTableRowType:g((e=>{switch(e){case"header":return t.makeRowsHeader;case"footer":return t.makeRowsFooter;default:return t.makeRowsBody}}))},((t,o)=>e.addCommand(o,t))),e.addCommand("mceInsertTable",((t,o)=>{((e,t,o,n={})=>{const r=e=>u(e)&&e>0;if(r(t)&&r(o)){const r=n.headerRows||0,s=n.headerColumns||0;return Fc(e,o,t,s,r)}console.error("Invalid values for mceInsertTable - rows and columns values are required to insert a table.")})(e,o.rows,o.columns,o.options)})),e.addCommand("mceTableApplyCellStyle",((t,o)=>{const l=e=>"tablecell"+e.toLowerCase().replace("-","");if(!s(o))return;const a=B(qs(e),ds);if(0===a.length)return;const c=((e,t)=>{const o={};return((e,t,o,n)=>{G(e,((e,r)=>{(t(e,r)?o:n)(e,r)}))})(e,t,(e=>(t,o)=>{e[o]=t})(o),f),o})(o,((t,o)=>e.formatter.has(l(o))&&r(t)));(e=>{for(const t in e)if(U.call(e,t))return!1;return!0})(c)||(G(c,((t,o)=>{const n=l(o);N(a,(o=>{""===t?e.formatter.remove(n,{value:null},o.dom,!0):e.formatter.apply(n,{value:t},o.dom)}))})),n(a[0]).each((t=>gc(e,t.dom,hc))))}))},ni=sa([{before:["element"]},{on:["element","offset"]},{after:["element"]}]),ri={before:ni.before,on:ni.on,after:ni.after,cata:(e,t,o,n)=>e.fold(t,o,n),getStart:e=>e.fold(h,h,h)},si=(e,t)=>({selection:e,kill:t}),li=(e,t)=>{const o=e.document.createRange();return o.selectNode(t.dom),o},ai=(e,t)=>{const o=e.document.createRange();return ci(o,t),o},ci=(e,t)=>e.selectNodeContents(t.dom),ii=(e,t,o)=>{const n=e.document.createRange();var r;return r=n,t.fold((e=>{r.setStartBefore(e.dom)}),((e,t)=>{r.setStart(e.dom,t)}),(e=>{r.setStartAfter(e.dom)})),((e,t)=>{t.fold((t=>{e.setEndBefore(t.dom)}),((t,o)=>{e.setEnd(t.dom,o)}),(t=>{e.setEndAfter(t.dom)}))})(n,o),n},mi=(e,t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},di=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom,width:e.width,height:e.height}),ui=sa([{ltr:["start","soffset","finish","foffset"]},{rtl:["start","soffset","finish","foffset"]}]),fi=(e,t,o)=>t(xe.fromDom(o.startContainer),o.startOffset,xe.fromDom(o.endContainer),o.endOffset),gi=(e,t)=>{const o=((e,t)=>t.match({domRange:e=>({ltr:g(e),rtl:C.none}),relative:(t,o)=>({ltr:Zt((()=>ii(e,t,o))),rtl:Zt((()=>C.some(ii(e,o,t))))}),exact:(t,o,n,r)=>({ltr:Zt((()=>mi(e,t,o,n,r))),rtl:Zt((()=>C.some(mi(e,n,r,t,o))))})}))(e,t);return((e,t)=>{const o=t.ltr();return o.collapsed?t.rtl().filter((e=>!1===e.collapsed)).map((e=>ui.rtl(xe.fromDom(e.endContainer),e.endOffset,xe.fromDom(e.startContainer),e.startOffset))).getOrThunk((()=>fi(0,ui.ltr,o))):fi(0,ui.ltr,o)})(0,o)},hi=(e,t)=>gi(e,t).match({ltr:(t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},rtl:(t,o,n,r)=>{const s=e.document.createRange();return s.setStart(n.dom,r),s.setEnd(t.dom,o),s}});ui.ltr,ui.rtl;const pi=(e,t,o,n)=>({start:e,soffset:t,finish:o,foffset:n}),bi=(e,t,o,n)=>({start:ri.on(e,t),finish:ri.on(o,n)}),wi=(e,t)=>{const o=hi(e,t);return pi(xe.fromDom(o.startContainer),o.startOffset,xe.fromDom(o.endContainer),o.endOffset)},vi=bi,yi=(e,t,o,n,r)=>Re(o,n)?C.none():Os(o,n,t).bind((t=>{const n=t.boxes.getOr([]);return n.length>1?(r(e,n,t.start,t.finish),C.some(si(C.some(vi(o,0,o,wr(o))),!0))):C.none()})),xi=(e,t)=>({item:e,mode:t}),Ci=(e,t,o,n=Si)=>e.property().parent(t).map((e=>xi(e,n))),Si=(e,t,o,n=Ti)=>o.sibling(e,t).map((e=>xi(e,n))),Ti=(e,t,o,n=Ti)=>{const r=e.property().children(t);return o.first(r).map((e=>xi(e,n)))},Ri=[{current:Ci,next:Si,fallback:C.none()},{current:Si,next:Ti,fallback:C.some(Ci)},{current:Ti,next:Ti,fallback:C.some(Si)}],Di=(e,t,o,n,r=Ri)=>L(r,(e=>e.current===o)).bind((o=>o.current(e,t,n,o.next).orThunk((()=>o.fallback.bind((o=>Di(e,t,o,n))))))),Oi=(e,t,o,n,r,s)=>Di(e,t,n,r).bind((t=>s(t.item)?C.none():o(t.item)?C.some(t.item):Oi(e,t.item,o,t.mode,r,s))),ki=e=>t=>0===e.property().children(t).length,Ei=(e,t,o,n)=>Oi(e,t,o,Si,{sibling:(e,t)=>e.query().prevSibling(t),first:e=>e.length>0?C.some(e[e.length-1]):C.none()},n),Ni=(e,t,o,n)=>Oi(e,t,o,Si,{sibling:(e,t)=>e.query().nextSibling(t),first:e=>e.length>0?C.some(e[0]):C.none()},n),_i=xs(),Bi=(e,t)=>((e,t,o)=>Ei(e,t,ki(e),o))(_i,e,t),zi=(e,t)=>((e,t,o)=>Ni(e,t,ki(e),o))(_i,e,t),Ai=sa([{none:["message"]},{success:[]},{failedUp:["cell"]},{failedDown:["cell"]}]),Li=e=>wt(e,"tr"),Wi={...Ai,verify:(e,t,o,n,r,s,l)=>wt(n,"td,th",l).bind((o=>wt(t,"td,th",l).map((t=>Re(o,t)?Re(n,o)&&wr(o)===r?s(t):Ai.none("in same cell"):Rs(Li,[o,t]).fold((()=>((e,t,o)=>{const n=e.getRect(t),r=e.getRect(o);return r.right>n.left&&r.lefts(t))))))).getOr(Ai.none("default")),cata:(e,t,o,n,r)=>e.fold(t,o,n,r)},Mi=ue("br"),ji=(e,t,o)=>t(e,o).bind((e=>ie(e)&&0===hr(e).trim().length?ji(e,t,o):C.some(e))),Pi=(e,t,o,n)=>((e,t)=>We(e,t).filter(Mi).orThunk((()=>We(e,t-1).filter(Mi))))(t,o).bind((t=>n.traverse(t).fold((()=>ji(t,n.gather,e).map(n.relative)),(e=>(e=>Ne(e).bind((t=>{const o=Le(t);return((e,t)=>W(e,b(Re,t)))(o,e).map((n=>((e,t,o,n)=>({parent:e,children:t,element:o,index:n}))(t,o,e,n)))})))(e).map((e=>ri.on(e.parent,e.index))))))),Ii=(e,t)=>({left:e.left,top:e.top+t,right:e.right,bottom:e.bottom+t}),Fi=(e,t)=>({left:e.left,top:e.top-t,right:e.right,bottom:e.bottom-t}),Hi=(e,t,o)=>({left:e.left+t,top:e.top+o,right:e.right+t,bottom:e.bottom+o}),$i=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom}),Vi=(e,t)=>C.some(e.getRect(t)),qi=(e,t,o)=>ce(t)?Vi(e,t).map($i):ie(t)?((e,t,o)=>o>=0&&o0?e.getRangedRect(t,o-1,t,o):C.none())(e,t,o).map($i):C.none(),Ui=(e,t)=>ce(t)?Vi(e,t).map($i):ie(t)?e.getRangedRect(t,0,t,wr(t)).map($i):C.none(),Gi=sa([{none:[]},{retry:["caret"]}]),Ki=(e,t,o)=>gt(t,xa).fold(y,(t=>Ui(e,t).exists((e=>((e,t)=>e.leftt.right)(o,e))))),Yi={point:e=>e.bottom,adjuster:(e,t,o,n,r)=>{const s=Ii(r,5);return Math.abs(o.bottom-n.bottom)<1||o.top>r.bottom?Gi.retry(s):o.top===r.bottom?Gi.retry(Ii(r,1)):Ki(e,t,r)?Gi.retry(Hi(s,5,0)):Gi.none()},move:Ii,gather:zi},Ji=(e,t,o,n,r)=>0===r?C.some(n):((e,t,o)=>e.elementFromPoint(t,o).filter((e=>"table"===ne(e))).isSome())(e,n.left,t.point(n))?((e,t,o,n,r)=>Ji(e,t,o,t.move(n,5),r))(e,t,o,n,r-1):e.situsFromPoint(n.left,t.point(n)).bind((s=>s.start.fold(C.none,(s=>Ui(e,s).bind((l=>t.adjuster(e,s,l,o,n).fold(C.none,(n=>Ji(e,t,o,n,r-1))))).orThunk((()=>C.some(n)))),C.none))),Qi=(e,t,o)=>{const n=e.move(o,5),r=Ji(t,e,o,n,100).getOr(n);return((e,t,o)=>e.point(t)>o.getInnerHeight()?C.some(e.point(t)-o.getInnerHeight()):e.point(t)<0?C.some(-e.point(t)):C.none())(e,r,t).fold((()=>t.situsFromPoint(r.left,e.point(r))),(o=>(t.scrollBy(0,o),t.situsFromPoint(r.left,e.point(r)-o))))},Xi={tryUp:b(Qi,{point:e=>e.top,adjuster:(e,t,o,n,r)=>{const s=Fi(r,5);return Math.abs(o.top-n.top)<1||o.bottome.getSelection().bind((n=>((e,t,o,n)=>{const r=Mi(t)?((e,t,o)=>o.traverse(t).orThunk((()=>ji(t,o.gather,e))).map(o.relative))(e,t,n):Pi(e,t,o,n);return r.map((e=>({start:e,finish:e})))})(t,n.finish,n.foffset,o).fold((()=>C.some(Gs(n.finish,n.foffset))),(r=>{const s=e.fromSitus(r);return l=Wi.verify(e,n.finish,n.foffset,s.finish,s.foffset,o.failure,t),Wi.cata(l,(e=>C.none()),(()=>C.none()),(e=>C.some(Gs(e,0))),(e=>C.some(Gs(e,wr(e)))));var l})))),em=(e,t,o,n,r,s)=>0===s?C.none():nm(e,t,o,n,r).bind((l=>{const a=e.fromSitus(l),c=Wi.verify(e,o,n,a.finish,a.foffset,r.failure,t);return Wi.cata(c,(()=>C.none()),(()=>C.some(l)),(l=>Re(o,l)&&0===n?tm(e,o,n,Fi,r):em(e,t,l,0,r,s-1)),(l=>Re(o,l)&&n===wr(l)?tm(e,o,n,Ii,r):em(e,t,l,wr(l),r,s-1)))})),tm=(e,t,o,n,r)=>qi(e,t,o).bind((t=>om(e,r,n(t,Xi.getJumpSize())))),om=(e,t,o)=>{const n=No().browser;return n.isChromium()||n.isSafari()||n.isFirefox()?t.retry(e,o):C.none()},nm=(e,t,o,n,r)=>qi(e,o,n).bind((t=>om(e,r,t))),rm=(e,t,o,n,r)=>wt(n,"td,th",t).bind((n=>wt(n,"table",t).bind((s=>((e,t)=>ft(e,(e=>Ne(e).exists((e=>Re(e,t)))),void 0).isSome())(r,s)?((e,t,o)=>Zi(e,t,o).bind((n=>em(e,t,n.element,n.offset,o,20).map(e.fromSitus))))(e,t,o).bind((e=>wt(e.finish,"td,th",t).map((t=>({start:n,finish:t,range:e}))))):C.none())))),sm=(e,t,o,n,r,s)=>s(n,t).orThunk((()=>rm(e,t,o,n,r).map((e=>{const t=e.range;return si(C.some(vi(t.start,t.soffset,t.finish,t.foffset)),!0)})))),lm=(e,t)=>wt(e,"tr",t).bind((e=>wt(e,"table",t).bind((o=>{const n=dt(o,"tr");return Re(e,n[0])?((e,t,o)=>Ei(_i,e,(e=>Cr(e).isSome()),o))(o,0,t).map((e=>{const t=wr(e);return si(C.some(vi(e,t,e,t)),!0)})):C.none()})))),am=(e,t)=>wt(e,"tr",t).bind((e=>wt(e,"table",t).bind((o=>{const n=dt(o,"tr");return Re(e,n[n.length-1])?((e,t,o)=>Ni(_i,e,(e=>xr(e).isSome()),o))(o,0,t).map((e=>si(C.some(vi(e,0,e,0)),!0))):C.none()})))),cm=(e,t,o,n,r,s,l)=>rm(e,o,n,r,s).bind((e=>yi(t,o,e.start,e.finish,l))),im=e=>{let t=e;return{get:()=>t,set:e=>{t=e}}},mm=()=>{const e=(e=>{const t=im(C.none()),o=()=>t.get().each(e);return{clear:()=>{o(),t.set(C.none())},isSet:()=>t.get().isSome(),get:()=>t.get(),set:e=>{o(),t.set(C.some(e))}}})(f);return{...e,on:t=>e.get().each(t)}},dm=(e,t)=>wt(e,"td,th",t),um=e=>_e(e).exists(es),fm={traverse:Ae,gather:zi,relative:ri.before,retry:Xi.tryDown,failure:Wi.failedDown},gm={traverse:ze,gather:Bi,relative:ri.before,retry:Xi.tryUp,failure:Wi.failedUp},hm=e=>t=>t===e,pm=hm(38),bm=hm(40),wm=e=>e>=37&&e<=40,vm={isBackward:hm(37),isForward:hm(39)},ym={isBackward:hm(39),isForward:hm(37)},xm=sa([{domRange:["rng"]},{relative:["startSitu","finishSitu"]},{exact:["start","soffset","finish","foffset"]}]),Cm={domRange:xm.domRange,relative:xm.relative,exact:xm.exact,exactFromRange:e=>xm.exact(e.start,e.soffset,e.finish,e.foffset),getWin:e=>{const t=(e=>e.match({domRange:e=>xe.fromDom(e.startContainer),relative:(e,t)=>ri.getStart(e),exact:(e,t,o,n)=>e}))(e);return xe.fromDom(Ee(t).dom.defaultView)},range:pi},Sm=(e,t)=>{const o=ne(e);return"input"===o?ri.after(e):D(["br","img"],o)?0===t?ri.before(e):ri.after(e):ri.on(e,t)},Tm=e=>C.from(e.getSelection()),Rm=(e,t)=>{Tm(e).each((e=>{e.removeAllRanges(),e.addRange(t)}))},Dm=(e,t,o,n,r)=>{const s=mi(e,t,o,n,r);Rm(e,s)},Om=(e,t)=>gi(e,t).match({ltr:(t,o,n,r)=>{Dm(e,t,o,n,r)},rtl:(t,o,n,r)=>{Tm(e).each((s=>{if(s.setBaseAndExtent)s.setBaseAndExtent(t.dom,o,n.dom,r);else if(s.extend)try{((e,t,o,n,r,s)=>{t.collapse(o.dom,n),t.extend(r.dom,s)})(0,s,t,o,n,r)}catch(s){Dm(e,n,r,t,o)}else Dm(e,n,r,t,o)}))}}),km=(e,t,o,n,r)=>{const s=((e,t,o,n)=>{const r=Sm(e,t),s=Sm(o,n);return Cm.relative(r,s)})(t,o,n,r);Om(e,s)},Em=(e,t,o)=>{const n=((e,t)=>{const o=e.fold(ri.before,Sm,ri.after),n=t.fold(ri.before,Sm,ri.after);return Cm.relative(o,n)})(t,o);Om(e,n)},Nm=e=>{if(e.rangeCount>0){const t=e.getRangeAt(0),o=e.getRangeAt(e.rangeCount-1);return C.some(pi(xe.fromDom(t.startContainer),t.startOffset,xe.fromDom(o.endContainer),o.endOffset))}return C.none()},_m=e=>{if(null===e.anchorNode||null===e.focusNode)return Nm(e);{const t=xe.fromDom(e.anchorNode),o=xe.fromDom(e.focusNode);return((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=ke(e).dom.createRange();return r.setStart(e.dom,t),r.setEnd(o.dom,n),r})(e,t,o,n),s=Re(e,o)&&t===n;return r.collapsed&&!s})(t,e.anchorOffset,o,e.focusOffset)?C.some(pi(t,e.anchorOffset,o,e.focusOffset)):Nm(e)}},Bm=(e,t,o=!0)=>{const n=(o?ai:li)(e,t);Rm(e,n)},zm=e=>(e=>Tm(e).filter((e=>e.rangeCount>0)).bind(_m))(e).map((e=>Cm.exact(e.start,e.soffset,e.finish,e.foffset))),Am=(e,t,o)=>((e,t,o)=>((e,t,o)=>e.caretPositionFromPoint?((e,t,o)=>{var n;return C.from(null===(n=e.caretPositionFromPoint)||void 0===n?void 0:n.call(e,t,o)).bind((t=>{if(null===t.offsetNode)return C.none();const o=e.createRange();return o.setStart(t.offsetNode,t.offset),o.collapse(),C.some(o)}))})(e,t,o):e.caretRangeFromPoint?((e,t,o)=>{var n;return C.from(null===(n=e.caretRangeFromPoint)||void 0===n?void 0:n.call(e,t,o))})(e,t,o):C.none())(e.document,t,o).map((e=>pi(xe.fromDom(e.startContainer),e.startOffset,xe.fromDom(e.endContainer),e.endOffset))))(e,t,o),Lm=e=>({elementFromPoint:(t,o)=>xe.fromPoint(xe.fromDom(e.document),t,o),getRect:e=>e.dom.getBoundingClientRect(),getRangedRect:(t,o,n,r)=>{const s=Cm.exact(t,o,n,r);return((e,t)=>(e=>{const t=e.getClientRects(),o=t.length>0?t[0]:e.getBoundingClientRect();return o.width>0||o.height>0?C.some(o).map(di):C.none()})(hi(e,t)))(e,s)},getSelection:()=>zm(e).map((t=>wi(e,t))),fromSitus:t=>{const o=Cm.relative(t.start,t.finish);return wi(e,o)},situsFromPoint:(t,o)=>Am(e,t,o).map((e=>bi(e.start,e.soffset,e.finish,e.foffset))),clearSelection:()=>{(e=>{Tm(e).each((e=>e.removeAllRanges()))})(e)},collapseSelection:(t=!1)=>{zm(e).each((o=>o.fold((e=>e.collapse(t)),((o,n)=>{const r=t?o:n;Em(e,r,r)}),((o,n,r,s)=>{const l=t?o:r,a=t?n:s;km(e,l,a,l,a)}))))},setSelection:t=>{km(e,t.start,t.soffset,t.finish,t.foffset)},setRelativeSelection:(t,o)=>{Em(e,t,o)},selectNode:t=>{Bm(e,t,!1)},selectContents:t=>{Bm(e,t)},getInnerHeight:()=>e.innerHeight,getScrollY:()=>(e=>{const t=void 0!==e?e.dom:document,o=t.body.scrollLeft||t.documentElement.scrollLeft,n=t.body.scrollTop||t.documentElement.scrollTop;return bn(o,n)})(xe.fromDom(e.document)).top,scrollBy:(t,o)=>{((e,t,o)=>{const n=(void 0!==o?o.dom:document).defaultView;n&&n.scrollBy(e,t)})(t,o,xe.fromDom(e.document))}}),Wm=(e,t)=>({rows:e,cols:t}),Mm=e=>gt(e,ae).exists(es),jm=(e,t)=>Mm(e)||Mm(t),Pm=e=>void 0!==e.dom.classList,Im=(e,t)=>((e,t,o)=>{const n=((e,t)=>{const o=pe(e,t);return void 0===o||""===o?[]:o.split(" ")})(e,t).concat([o]);return ge(e,t,n.join(" ")),!0})(e,"class",t),Fm=(e,t)=>{Pm(e)?e.dom.classList.add(t):Im(e,t)},Hm=(e,t)=>Pm(e)&&e.dom.classList.contains(t),$m=()=>({tag:"none"}),Vm=e=>({tag:"multiple",elements:e}),qm=e=>({tag:"single",element:e}),Um=e=>{const t=xe.fromDom((e=>{if(m(e.target)){const t=xe.fromDom(e.target);if(ce(t)&&m(t.dom.shadowRoot)&&e.composed&&e.composedPath){const t=e.composedPath();if(t)return H(t)}}return C.from(e.target)})(e).getOr(e.target)),o=()=>e.stopPropagation(),n=()=>e.preventDefault(),r=(s=n,l=o,(...e)=>s(l.apply(null,e)));var s,l;return((e,t,o,n,r,s,l)=>({target:e,x:t,y:o,stop:n,prevent:r,kill:s,raw:l}))(t,e.clientX,e.clientY,o,n,r,e)},Gm=(e,t,o,n)=>{e.dom.removeEventListener(t,o,n)},Km=x,Ym=(e,t,o)=>((e,t,o,n)=>((e,t,o,n,r)=>{const s=((e,t)=>o=>{e(o)&&t(Um(o))})(o,n);return e.dom.addEventListener(t,s,r),{unbind:b(Gm,e,t,s,r)}})(e,t,o,n,!1))(e,t,Km,o),Jm=Um,Qm=e=>!Hm(xe.fromDom(e.target),"ephox-snooker-resizer-bar"),Xm=(e,t)=>{const o=(r=Is.selectedSelector,{get:()=>_s(xe.fromDom(e.getBody()),r).fold((()=>Vs(ss(e),ns(e)).fold($m,qm)),Vm)}),n=((e,t,o)=>{const n=t=>{we(t,e.selected),we(t,e.firstSelected),we(t,e.lastSelected)},r=t=>{ge(t,e.selected,"1")},s=e=>{l(e),o()},l=t=>{const o=dt(t,`${e.selectedSelector},${e.firstSelectedSelector},${e.lastSelectedSelector}`);N(o,n)};return{clearBeforeUpdate:l,clear:s,selectRange:(o,n,l,a)=>{s(o),N(n,r),ge(l,e.firstSelected,"1"),ge(a,e.lastSelected,"1"),t(n,l,a)},selectedSelector:e.selectedSelector,firstSelectedSelector:e.firstSelectedSelector,lastSelectedSelector:e.lastSelectedSelector}})(Is,((t,o,n)=>{Gt(o).each((r=>{const s=E(t,(e=>e.dom)),l=Wr(e),a=_r(f,xe.fromDom(e.getDoc()),l),c=((e,t,o)=>{const n=Xo(e);return zl(n,t).map((e=>{const t=Ol(n,o,!1),{rows:r}=Vo(t),s=((e,t)=>{const o=e.slice(0,t[t.length-1].row+1),n=kl(o);return j(n,(e=>{const o=e.cells.slice(0,t[t.length-1].column+1);return E(o,(e=>e.element))}))})(r,e),l=((e,t)=>{const o=e.slice(t[0].row+t[0].rowspan-1,e.length),n=kl(o);return j(n,(e=>{const o=e.cells.slice(t[0].column+t[0].colspan-1,e.cells.length);return E(o,(e=>e.element))}))})(r,e);return{upOrLeftCells:s,downOrRightCells:l}}))})(r,{selection:qs(e)},a).map((e=>K(e,(e=>E(e,(e=>e.dom)))))).getOrUndefined();((e,t,o,n,r)=>{e.dispatch("TableSelectionChange",{cells:t,start:o,finish:n,otherCells:r})})(e,s,o.dom,n.dom,c)}))}),(()=>(e=>{e.dispatch("TableSelectionClear")})(e)));var r;return e.on("init",(o=>{const r=e.getWin(),s=os(e),l=ns(e),a=((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=mm(),s=r.clear,l=s=>{r.on((r=>{n.clearBeforeUpdate(t),dm(s.target,o).each((l=>{Os(r,l,o).each((o=>{const r=o.boxes.getOr([]);if(1===r.length){const e=r[0],o="false"===ts(e),l=vt(Zr(s.target),e,Re);o&&l&&n.selectRange(t,r,e,e)}else r.length>1&&(n.selectRange(t,r,o.start,o.finish),e.selectContents(l))}))}))}))};return{clearstate:s,mousedown:e=>{n.clear(t),dm(e.target,o).filter(um).each(r.set)},mouseover:e=>{l(e)},mouseup:e=>{l(e),s()}}})(Lm(e),t,o,n);return{clearstate:r.clearstate,mousedown:r.mousedown,mouseover:r.mouseover,mouseup:r.mouseup}})(r,s,l,n),c=((e,t,o,n)=>{const r=Lm(e),s=()=>(n.clear(t),C.none());return{keydown:(e,l,a,c,i,m)=>{const d=e.raw,u=d.which,f=!0===d.shiftKey,g=ks(t,n.selectedSelector).fold((()=>(wm(u)&&!f&&n.clearBeforeUpdate(t),wm(u)&&f&&!jm(l,c)?C.none:bm(u)&&f?b(cm,r,t,o,fm,c,l,n.selectRange):pm(u)&&f?b(cm,r,t,o,gm,c,l,n.selectRange):bm(u)?b(sm,r,o,fm,c,l,am):pm(u)?b(sm,r,o,gm,c,l,lm):C.none)),(e=>{const o=o=>()=>{const s=V(o,(o=>((e,t,o,n,r)=>Ns(n,e,t,r.firstSelectedSelector,r.lastSelectedSelector).map((e=>(r.clearBeforeUpdate(o),r.selectRange(o,e.boxes,e.start,e.finish),e.boxes))))(o.rows,o.cols,t,e,n)));return s.fold((()=>Es(t,n.firstSelectedSelector,n.lastSelectedSelector).map((e=>{const o=bm(u)||m.isForward(u)?ri.after:ri.before;return r.setRelativeSelection(ri.on(e.first,0),o(e.table)),n.clear(t),si(C.none(),!0)}))),(e=>C.some(si(C.none(),!0))))};return wm(u)&&f&&!jm(l,c)?C.none:bm(u)&&f?o([Wm(1,0)]):pm(u)&&f?o([Wm(-1,0)]):m.isBackward(u)&&f?o([Wm(0,-1),Wm(-1,0)]):m.isForward(u)&&f?o([Wm(0,1),Wm(1,0)]):wm(u)&&!f?s:C.none}));return g()},keyup:(e,r,s,l,a)=>ks(t,n.selectedSelector).fold((()=>{const c=e.raw,i=c.which;return!0===c.shiftKey&&wm(i)&&jm(r,l)?((e,t,o,n,r,s,l)=>Re(o,r)&&n===s?C.none():wt(o,"td,th",t).bind((o=>wt(r,"td,th",t).bind((n=>yi(e,t,o,n,l))))))(t,o,r,s,l,a,n.selectRange):C.none()}),C.none)}})(r,s,l,n),i=((e,t,o,n)=>{const r=Lm(e);return(e,s)=>{n.clearBeforeUpdate(t),Os(e,s,o).each((e=>{const o=e.boxes.getOr([]);n.selectRange(t,o,e.start,e.finish),r.selectContents(s),r.collapseSelection()}))}})(r,s,l,n);e.on("TableSelectorChange",(e=>i(e.start,e.finish)));const m=(t,o)=>{(e=>!0===e.raw.shiftKey)(t)&&(o.kill&&t.kill(),o.selection.each((t=>{const o=Cm.relative(t.start,t.finish),n=hi(r,o);e.selection.setRng(n)})))},d=e=>0===e.button,u=(()=>{const e=im(xe.fromDom(s)),t=im(0);return{touchEnd:o=>{const n=xe.fromDom(o.target);if(ue("td")(n)||ue("th")(n)){const r=e.get(),s=t.get();Re(r,n)&&o.timeStamp-s<300&&(o.preventDefault(),i(n,n))}e.set(n),t.set(o.timeStamp)}}})();e.on("dragstart",(e=>{a.clearstate()})),e.on("mousedown",(e=>{d(e)&&Qm(e)&&a.mousedown(Jm(e))})),e.on("mouseover",(e=>{var t;(void 0===(t=e).buttons||1&t.buttons)&&Qm(e)&&a.mouseover(Jm(e))})),e.on("mouseup",(e=>{d(e)&&Qm(e)&&a.mouseup(Jm(e))})),e.on("touchend",u.touchEnd),e.on("keyup",(t=>{const o=Jm(t);if(o.raw.shiftKey&&wm(o.raw.which)){const t=e.selection.getRng(),n=xe.fromDom(t.startContainer),r=xe.fromDom(t.endContainer);c.keyup(o,n,t.startOffset,r,t.endOffset).each((e=>{m(o,e)}))}})),e.on("keydown",(o=>{const n=Jm(o);t.hide();const r=e.selection.getRng(),s=xe.fromDom(r.startContainer),l=xe.fromDom(r.endContainer),a=dn(vm,ym)(xe.fromDom(e.selection.getStart()));c.keydown(n,s,r.startOffset,l,r.endOffset,a).each((e=>{m(n,e)})),t.show()})),e.on("NodeChange",(()=>{const t=e.selection,o=xe.fromDom(t.getStart()),r=xe.fromDom(t.getEnd());Rs(Gt,[o,r]).fold((()=>n.clear(s)),f)}))})),e.on("PreInit",(()=>{e.serializer.addTempAttr(Is.firstSelected),e.serializer.addTempAttr(Is.lastSelected)})),{getSelectedCells:()=>((e,t)=>{switch(e.tag){case"none":return t();case"single":return(e=>[e.dom])(e.element);case"multiple":return(e=>E(e,(e=>e.dom)))(e.elements)}})(o.get(),g([])),clearSelectedCells:e=>n.clear(xe.fromDom(e))}},Zm=e=>{let t=[];return{bind:e=>{if(void 0===e)throw new Error("Event bind error: undefined handler");t.push(e)},unbind:e=>{t=B(t,(t=>t!==e))},trigger:(...o)=>{const n={};N(e,((e,t)=>{n[e]=o[t]})),N(t,(e=>{e(n)}))}}},ed=e=>({registry:K(e,(e=>({bind:e.bind,unbind:e.unbind}))),trigger:K(e,(e=>e.trigger))}),td=e=>e.slice(0).sort(),od=(e,t)=>{const o=B(t,(t=>!D(e,t)));o.length>0&&(e=>{throw new Error("Unsupported keys for object: "+td(e).join(", "))})(o)},nd=e=>((e,t)=>((e,t,o)=>{if(0===t.length)throw new Error("You must specify at least one required field.");return((e,t)=>{if(!l(t))throw new Error("The "+e+" fields must be an array. Was: "+t+".");N(t,(t=>{if(!r(t))throw new Error("The value "+t+" in the "+e+" fields was not a string.")}))})("required",t),(e=>{const t=td(e);L(t,((e,o)=>o{throw new Error("The field: "+e+" occurs more than once in the combined fields: ["+t.join(", ")+"].")}))})(t),n=>{const r=q(n);P(t,(e=>D(r,e)))||((e,t)=>{throw new Error("All required keys ("+td(e).join(", ")+") were not specified. Specified keys were: "+td(t).join(", ")+".")})(t,r),e(t,r);const s=B(t,(e=>!o.validate(n[e],e)));return s.length>0&&((e,t)=>{throw new Error("All values need to be of type: "+t+". Keys ("+td(e).join(", ")+") were not.")})(s,o.label),n}})(e,t,{validate:d,label:"function"}))(od,e),rd=nd(["compare","extract","mutate","sink"]),sd=nd(["element","start","stop","destroy"]),ld=nd(["forceDrop","drop","move","delayDrop"]),ad=()=>{const e=(()=>{const e=ed({move:Zm(["info"])});return{onEvent:f,reset:f,events:e.registry}})(),t=(()=>{let e=C.none();const t=ed({move:Zm(["info"])});return{onEvent:(o,n)=>{n.extract(o).each((o=>{const r=((t,o)=>{const n=e.map((e=>t.compare(e,o)));return e=C.some(o),n})(n,o);r.each((e=>{t.trigger.move(e)}))}))},reset:()=>{e=C.none()},events:t.registry}})();let o=e;return{on:()=>{o.reset(),o=t},off:()=>{o.reset(),o=e},isOn:()=>o===t,onEvent:(e,t)=>{o.onEvent(e,t)},events:t.events}},cd=e=>{const t=e.replace(/\./g,"-");return{resolve:e=>t+"-"+e}},id=cd("ephox-dragster").resolve;var md=rd({compare:(e,t)=>bn(t.left-e.left,t.top-e.top),extract:e=>C.some(bn(e.x,e.y)),sink:(e,t)=>{const o=(e=>{const t={layerClass:id("blocker"),...e},o=xe.fromTag("div");return ge(o,"role","presentation"),_t(o,{position:"fixed",left:"0px",top:"0px",width:"100%",height:"100%"}),Fm(o,id("blocker")),Fm(o,t.layerClass),{element:g(o),destroy:()=>{qe(o)}}})(t),n=Ym(o.element(),"mousedown",e.forceDrop),r=Ym(o.element(),"mouseup",e.drop),s=Ym(o.element(),"mousemove",e.move),l=Ym(o.element(),"mouseout",e.delayDrop);return sd({element:o.element,start:e=>{Ie(e,o.element())},stop:()=>{qe(o.element())},destroy:()=>{o.destroy(),r.unbind(),s.unbind(),l.unbind(),n.unbind()}})},mutate:(e,t)=>{e.mutate(t.left,t.top)}});const dd=cd("ephox-snooker").resolve,ud=dd("resizer-bar"),fd=dd("resizer-rows"),gd=dd("resizer-cols"),hd=e=>{const t=dt(e.parent(),"."+ud);N(t,qe)},pd=(e,t,o)=>{const n=e.origin();N(t,(t=>{t.each((t=>{const r=o(n,t);Fm(r,ud),Ie(e.parent(),r)}))}))},bd=(e,t,o,n,r)=>{const s=vn(o),l=t.isResizable,a=n.length>0?_n.positions(n,o):[],c=a.length>0?((e,t)=>j(e.all,((e,o)=>t(e.element)?[o]:[])))(e,l):[];((e,t,o,n)=>{pd(e,t,((e,t)=>{const r=((e,t,o,n)=>{const r=xe.fromTag("div");return _t(r,{position:"absolute",left:t+"px",top:o-3.5+"px",height:"7px",width:n+"px"}),he(r,{"data-row":e,role:"presentation"}),r})(t.row,o.left-e.left,t.y-e.top,n);return Fm(r,fd),r}))})(t,B(a,((e,t)=>O(c,(e=>t===e)))),s,Lo(o));const i=r.length>0?zn.positions(r,o):[],m=i.length>0?((e,t)=>{const o=[];return k(e.grid.columns,(n=>{ln(e,n).map((e=>e.element)).forall(t)&&o.push(n)})),B(o,(o=>{const n=on(e,(e=>e.column===o));return P(n,(e=>t(e.element)))}))})(e,l):[];((e,t,o,n)=>{pd(e,t,((e,t)=>{const r=((e,t,o,n,r)=>{const s=xe.fromTag("div");return _t(s,{position:"absolute",left:t-3.5+"px",top:o+"px",height:r+"px",width:"7px"}),he(s,{"data-column":e,role:"presentation"}),s})(t.col,t.x-e.left,o.top-e.top,0,n);return Fm(r,gd),r}))})(t,B(i,((e,t)=>O(m,(e=>t===e)))),s,hn(o))},wd=(e,t)=>{if(hd(e),e.isResizable(t)){const o=Xo(t),n=mn(o),r=an(o);bd(o,e,t,n,r)}},vd=(e,t)=>{const o=dt(e.parent(),"."+ud);N(o,t)},yd=e=>{vd(e,(e=>{Nt(e,"display","none")}))},xd=e=>{vd(e,(e=>{Nt(e,"display","block")}))},Cd=dd("resizer-bar-dragging"),Sd=e=>{const t=(()=>{const e=ed({drag:Zm(["xDelta","yDelta","target"])});let t=C.none();const o=(()=>{const e=ed({drag:Zm(["xDelta","yDelta"])});return{mutate:(t,o)=>{e.trigger.drag(t,o)},events:e.registry}})();return o.events.drag.bind((o=>{t.each((t=>{e.trigger.drag(o.xDelta,o.yDelta,t)}))})),{assign:e=>{t=C.some(e)},get:()=>t,mutate:o.mutate,events:e.registry}})(),o=((e,t={})=>{var o;return((e,t,o)=>{let n=!1;const r=ed({start:Zm([]),stop:Zm([])}),s=ad(),l=()=>{m.stop(),s.isOn()&&(s.off(),r.trigger.stop())},c=(e=>{let t=null;const o=()=>{a(t)||(clearTimeout(t),t=null)};return{cancel:o,throttle:(...n)=>{o(),t=setTimeout((()=>{t=null,e.apply(null,n)}),200)}}})(l);s.events.move.bind((o=>{t.mutate(e,o.info)}));const i=e=>(...t)=>{n&&e.apply(null,t)},m=t.sink(ld({forceDrop:l,drop:i(l),move:i((e=>{c.cancel(),s.onEvent(e,t)})),delayDrop:i(c.throttle)}),o);return{element:m.element,go:e=>{m.start(e),s.on(),r.trigger.start()},on:()=>{n=!0},off:()=>{n=!1},isActive:()=>n,destroy:()=>{m.destroy()},events:r.registry}})(e,null!==(o=t.mode)&&void 0!==o?o:md,t)})(t,{});let n=C.none();const r=(e,t)=>C.from(pe(e,t));t.events.drag.bind((e=>{r(e.target,"data-row").each((t=>{const o=Pt(e.target,"top");Nt(e.target,"top",o+e.yDelta+"px")})),r(e.target,"data-column").each((t=>{const o=Pt(e.target,"left");Nt(e.target,"left",o+e.xDelta+"px")}))}));const s=(e,t)=>Pt(e,t)-Wt(e,"data-initial-"+t,0);o.events.stop.bind((()=>{t.get().each((t=>{n.each((o=>{r(t,"data-row").each((e=>{const n=s(t,"top");we(t,"data-initial-top"),d.trigger.adjustHeight(o,n,parseInt(e,10))})),r(t,"data-column").each((e=>{const n=s(t,"left");we(t,"data-initial-left"),d.trigger.adjustWidth(o,n,parseInt(e,10))})),wd(e,o)}))}))}));const l=(n,r)=>{d.trigger.startAdjust(),t.assign(n),ge(n,"data-initial-"+r,Pt(n,r)),Fm(n,Cd),Nt(n,"opacity","0.2"),o.go(e.dragContainer())},c=Ym(e.parent(),"mousedown",(e=>{var t;t=e.target,Hm(t,fd)&&l(e.target,"top"),(e=>Hm(e,gd))(e.target)&&l(e.target,"left")})),i=t=>Re(t,e.view()),m=Ym(e.view(),"mouseover",(t=>{var r;(r=t.target,wt(r,"table",i).filter(es)).fold((()=>{st(t.target)&&hd(e)}),(t=>{o.isActive()&&(n=C.some(t),wd(e,t))}))})),d=ed({adjustHeight:Zm(["table","delta","row"]),adjustWidth:Zm(["table","delta","column"]),startAdjust:Zm([])});return{destroy:()=>{c.unbind(),m.unbind(),o.destroy(),hd(e)},refresh:t=>{wd(e,t)},on:o.on,off:o.off,hideBars:b(yd,e),showBars:b(xd,e),events:d.registry}};let Td=0;const Rd=(e,t)=>{const o=(e=>!(e=>e.inline&&(e=>{var t;if(!e.inline)return C.none();const o=null!==(t=Jr(e))&&void 0!==t?t:"";if(o.length>0)return bt(lt(),o);const n=Qr(e);return m(n)?C.some(xe.fromDom(n)):C.none()})(e).isSome())(e)&&"split"===Xr(e))(e),n=xe.fromDom(e.getBody()),r=(e=>{const t=(e=>{const t=(new Date).getTime(),o=Math.floor(window.crypto.getRandomValues(new Uint32Array(1))[0]/4294967295*1e9);return Td++,e+"_"+o+Td+String(t)})("resizer-container"),o=xe.fromTag("div");return ge(o,"id",t),_t(o,{position:e,height:"0",width:"0",padding:"0",margin:"0",border:"0"}),o})(o?"relative":"static"),s=lt();return o?(je(n,r),((e,t,o,n)=>({parent:g(t),view:g(e),dragContainer:g(o),origin:()=>vn(t),isResizable:n}))(n,r,s,t)):(Ie(s,r),((e,t,o)=>({parent:g(t),view:g(e),dragContainer:g(t),origin:g(bn(0,0)),isResizable:o}))(n,r,t))},Dd=e=>m(e)&&"TABLE"===e.nodeName,Od="bar-",kd=e=>"false"!==pe(e,"data-mce-resize"),Ed=e=>{const t=mm(),o=mm(),n=mm();let r,s,l,a;const c=t=>wc(e,t),i=()=>Pr(e)?ll():sl(),m=(t,o,n,m)=>{const d=(e=>{return Tt(t=e,"corner-")?(e=>e.substring(7))(t):t;var t})(o),u=Rt(d,"e"),f=Tt(d,"n");if(""===s&&Lc(t),""===a&&(e=>{const t=(e=>gn(e)+"px")(e);Nc(e,C.none(),C.some(t)),Ac(e)})(t),n!==r&&""!==s){Nt(t,"width",s);const o=i(),l=c(t),a=Pr(e)||u?(e=>al(e).columns)(t)-1:0;ca(t,n-r,a,o,l)}else if((e=>/^(\d+(\.\d+)?)%$/.test(e))(s)){const e=parseFloat(s.replace("%",""));Nt(t,"width",n*e/r+"%")}if((e=>/^(\d+(\.\d+)?)px$/.test(e))(s)&&(e=>{const t=Xo(e);sn(t)||N(qt(e),(e=>{const t=Bt(e,"width");Nt(e,"width",t),we(e,"width")}))})(t),m!==l&&""!==a){Nt(t,"height",a);const e=f?0:(e=>al(e).rows)(t)-1;ia(t,m-l,e)}};e.on("init",(()=>{const r=((e,t)=>e.inline?Rd(e,t):((e,t)=>{const o=me(e)?(e=>xe.fromDom(Ee(e).dom.documentElement))(e):e;return{parent:g(o),view:g(e),dragContainer:g(o),origin:g(bn(0,0)),isResizable:t}})(xe.fromDom(e.getDoc()),t))(e,kd);if(n.set(r),(e=>{const t=e.options.get("object_resizing");return D(t.split(","),"table")})(e)&&qr(e)){const n=((e,t,o)=>{const n=_n,r=zn,s=Sd(e),l=ed({beforeResize:Zm(["table","type"]),afterResize:Zm(["table","type"]),startDrag:Zm([])});return s.events.adjustHeight.bind((e=>{const t=e.table;l.trigger.beforeResize(t,"row");const o=n.delta(e.delta,t);ia(t,o,e.row),l.trigger.afterResize(t,"row")})),s.events.startAdjust.bind((e=>{l.trigger.startDrag()})),s.events.adjustWidth.bind((e=>{const n=e.table;l.trigger.beforeResize(n,"col");const s=r.delta(e.delta,n),a=o(n);ca(n,s,e.column,t,a),l.trigger.afterResize(n,"col")})),{on:s.on,off:s.off,refreshBars:s.refresh,hideBars:s.hideBars,showBars:s.showBars,destroy:s.destroy,events:l.registry}})(r,i(),c);e.mode.isReadOnly()||n.on(),n.events.startDrag.bind((o=>{t.set(e.selection.getRng())})),n.events.beforeResize.bind((t=>{const o=t.table.dom;((e,t,o,n,r)=>{e.dispatch("ObjectResizeStart",{target:t,width:o,height:n,origin:r})})(e,o,ls(o),as(o),Od+t.type)})),n.events.afterResize.bind((o=>{const n=o.table,r=n.dom;rs(n),t.on((t=>{e.selection.setRng(t),e.focus()})),((e,t,o,n,r)=>{e.dispatch("ObjectResized",{target:t,width:o,height:n,origin:r})})(e,r,ls(r),as(r),Od+o.type),e.undoManager.add()})),o.set(n)}})),e.on("ObjectResizeStart",(t=>{const o=t.target;if(Dd(o)&&!e.mode.isReadOnly()){const n=xe.fromDom(o);N(e.dom.select(".mce-clonedresizable"),(t=>{e.dom.addClass(t,"mce-"+jr(e)+"-columns")})),!Bc(n)&&$r(e)?Wc(n):!_c(n)&&Hr(e)&&Lc(n),zc(n)&&Tt(t.origin,Od)&&Lc(n),r=t.width,s=Vr(e)?"":is(e,o).getOr(""),l=t.height,a=ms(e,o).getOr("")}})),e.on("ObjectResized",(t=>{const o=t.target;if(Dd(o)){const n=xe.fromDom(o),r=t.origin;(e=>Tt(e,"corner-"))(r)&&m(n,r,t.width,t.height),rs(n),gc(e,n.dom,hc)}}));const d=()=>{o.on((e=>{e.on(),e.showBars()}))},u=()=>{o.on((e=>{e.off(),e.hideBars()}))};return e.on("DisabledStateChange",(e=>{e.state?u():d()})),e.on("SwitchMode",(()=>{e.mode.isReadOnly()?u():d()})),e.on("dragstart dragend",(e=>{"dragstart"===e.type?u():d()})),e.on("remove",(()=>{o.on((e=>{e.destroy()})),n.on((t=>{((e,t)=>{e.inline&&qe(t.parent())})(e,t)}))})),{refresh:e=>{o.on((t=>t.refreshBars(xe.fromDom(e))))},hide:()=>{o.on((e=>e.hideBars()))},show:()=>{o.on((e=>e.showBars()))}}},Nd=e=>{(e=>{const t=e.options.register;t("table_clone_elements",{processor:"string[]"}),t("table_use_colgroups",{processor:"boolean",default:!0}),t("table_header_type",{processor:e=>{const t=D(["section","cells","sectionCells","auto"],e);return t?{value:e,valid:t}:{valid:!1,message:"Must be one of: section, cells, sectionCells or auto."}},default:"section"}),t("table_sizing_mode",{processor:"string",default:"auto"}),t("table_default_attributes",{processor:"object",default:{border:"1"}}),t("table_default_styles",{processor:"object",default:{"border-collapse":"collapse"}}),t("table_column_resizing",{processor:e=>{const t=D(["preservetable","resizetable"],e);return t?{value:e,valid:t}:{valid:!1,message:"Must be preservetable, or resizetable."}},default:"preservetable"}),t("table_resize_bars",{processor:"boolean",default:!0}),t("table_style_by_css",{processor:"boolean",default:!0}),t("table_merge_content_on_paste",{processor:"boolean",default:!0})})(e);const t=Ed(e),o=Xm(e,t),n=vc(e,t,o);return oi(e,n),((e,t)=>{const o=ns(e),n=t=>Vs(ss(e)).bind((n=>Gt(n,o).map((o=>{const r=Fs(qs(e),o,n);return t(o,r)})))).getOr("");G({mceTableRowType:()=>n(t.getTableRowType),mceTableCellType:()=>n(t.getTableCellType),mceTableColType:()=>n(t.getTableColType)},((t,o)=>e.addQueryValueHandler(o,t)))})(e,n),Us(e,n),{getSelectedCells:o.getSelectedCells,clearSelectedCells:o.clearSelectedCells}};e.add("dom",(e=>({table:Nd(e)})))}();PKA \T܌܌ dom/model.jsnu[/** * TinyMCE version 7.7.1 (2025-03-05) */ (function () { 'use strict'; var global$1 = tinymce.util.Tools.resolve('tinymce.ModelManager'); const hasProto = (v, constructor, predicate) => { var _a; if (predicate(v, constructor.prototype)) { return true; } else { return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name; } }; const typeOf = x => { const t = typeof x; if (x === null) { return 'null'; } else if (t === 'object' && Array.isArray(x)) { return 'array'; } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) { return 'string'; } else { return t; } }; const isType$1 = type => value => typeOf(value) === type; const isSimpleType = type => value => typeof value === type; const eq$2 = t => a => t === a; const isString = isType$1('string'); const isObject = isType$1('object'); const isArray = isType$1('array'); const isNull = eq$2(null); const isBoolean = isSimpleType('boolean'); const isUndefined = eq$2(undefined); const isNullable = a => a === null || a === undefined; const isNonNullable = a => !isNullable(a); const isFunction = isSimpleType('function'); const isNumber = isSimpleType('number'); const noop = () => { }; const compose = (fa, fb) => { return (...args) => { return fa(fb.apply(null, args)); }; }; const compose1 = (fbc, fab) => a => fbc(fab(a)); const constant = value => { return () => { return value; }; }; const identity = x => { return x; }; const tripleEquals = (a, b) => { return a === b; }; function curry(fn, ...initialArgs) { return (...restArgs) => { const all = initialArgs.concat(restArgs); return fn.apply(null, all); }; } const not = f => t => !f(t); const die = msg => { return () => { throw new Error(msg); }; }; const apply = f => { return f(); }; const never = constant(false); const always = constant(true); class Optional { constructor(tag, value) { this.tag = tag; this.value = value; } static some(value) { return new Optional(true, value); } static none() { return Optional.singletonNone; } fold(onNone, onSome) { if (this.tag) { return onSome(this.value); } else { return onNone(); } } isSome() { return this.tag; } isNone() { return !this.tag; } map(mapper) { if (this.tag) { return Optional.some(mapper(this.value)); } else { return Optional.none(); } } bind(binder) { if (this.tag) { return binder(this.value); } else { return Optional.none(); } } exists(predicate) { return this.tag && predicate(this.value); } forall(predicate) { return !this.tag || predicate(this.value); } filter(predicate) { if (!this.tag || predicate(this.value)) { return this; } else { return Optional.none(); } } getOr(replacement) { return this.tag ? this.value : replacement; } or(replacement) { return this.tag ? this : replacement; } getOrThunk(thunk) { return this.tag ? this.value : thunk(); } orThunk(thunk) { return this.tag ? this : thunk(); } getOrDie(message) { if (!this.tag) { throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None'); } else { return this.value; } } static from(value) { return isNonNullable(value) ? Optional.some(value) : Optional.none(); } getOrNull() { return this.tag ? this.value : null; } getOrUndefined() { return this.value; } each(worker) { if (this.tag) { worker(this.value); } } toArray() { return this.tag ? [this.value] : []; } toString() { return this.tag ? `some(${ this.value })` : 'none()'; } } Optional.singletonNone = new Optional(false); const nativeSlice = Array.prototype.slice; const nativeIndexOf = Array.prototype.indexOf; const nativePush = Array.prototype.push; const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t); const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1; const exists = (xs, pred) => { for (let i = 0, len = xs.length; i < len; i++) { const x = xs[i]; if (pred(x, i)) { return true; } } return false; }; const range$1 = (num, f) => { const r = []; for (let i = 0; i < num; i++) { r.push(f(i)); } return r; }; const map$1 = (xs, f) => { const len = xs.length; const r = new Array(len); for (let i = 0; i < len; i++) { const x = xs[i]; r[i] = f(x, i); } return r; }; const each$2 = (xs, f) => { for (let i = 0, len = xs.length; i < len; i++) { const x = xs[i]; f(x, i); } }; const eachr = (xs, f) => { for (let i = xs.length - 1; i >= 0; i--) { const x = xs[i]; f(x, i); } }; const partition = (xs, pred) => { const pass = []; const fail = []; for (let i = 0, len = xs.length; i < len; i++) { const x = xs[i]; const arr = pred(x, i) ? pass : fail; arr.push(x); } return { pass, fail }; }; const filter$2 = (xs, pred) => { const r = []; for (let i = 0, len = xs.length; i < len; i++) { const x = xs[i]; if (pred(x, i)) { r.push(x); } } return r; }; const foldr = (xs, f, acc) => { eachr(xs, (x, i) => { acc = f(acc, x, i); }); return acc; }; const foldl = (xs, f, acc) => { each$2(xs, (x, i) => { acc = f(acc, x, i); }); return acc; }; const findUntil = (xs, pred, until) => { for (let i = 0, len = xs.length; i < len; i++) { const x = xs[i]; if (pred(x, i)) { return Optional.some(x); } else if (until(x, i)) { break; } } return Optional.none(); }; const find$1 = (xs, pred) => { return findUntil(xs, pred, never); }; const findIndex = (xs, pred) => { for (let i = 0, len = xs.length; i < len; i++) { const x = xs[i]; if (pred(x, i)) { return Optional.some(i); } } return Optional.none(); }; const flatten = xs => { const r = []; for (let i = 0, len = xs.length; i < len; ++i) { if (!isArray(xs[i])) { throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); } nativePush.apply(r, xs[i]); } return r; }; const bind$2 = (xs, f) => flatten(map$1(xs, f)); const forall = (xs, pred) => { for (let i = 0, len = xs.length; i < len; ++i) { const x = xs[i]; if (pred(x, i) !== true) { return false; } } return true; }; const reverse = xs => { const r = nativeSlice.call(xs, 0); r.reverse(); return r; }; const mapToObject = (xs, f) => { const r = {}; for (let i = 0, len = xs.length; i < len; i++) { const x = xs[i]; r[String(x)] = f(x, i); } return r; }; const sort$1 = (xs, comparator) => { const copy = nativeSlice.call(xs, 0); copy.sort(comparator); return copy; }; const get$d = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none(); const head = xs => get$d(xs, 0); const last$2 = xs => get$d(xs, xs.length - 1); const findMap = (arr, f) => { for (let i = 0; i < arr.length; i++) { const r = f(arr[i], i); if (r.isSome()) { return r; } } return Optional.none(); }; const keys = Object.keys; const hasOwnProperty = Object.hasOwnProperty; const each$1 = (obj, f) => { const props = keys(obj); for (let k = 0, len = props.length; k < len; k++) { const i = props[k]; const x = obj[i]; f(x, i); } }; const map = (obj, f) => { return tupleMap(obj, (x, i) => ({ k: i, v: f(x, i) })); }; const tupleMap = (obj, f) => { const r = {}; each$1(obj, (x, i) => { const tuple = f(x, i); r[tuple.k] = tuple.v; }); return r; }; const objAcc = r => (x, i) => { r[i] = x; }; const internalFilter = (obj, pred, onTrue, onFalse) => { each$1(obj, (x, i) => { (pred(x, i) ? onTrue : onFalse)(x, i); }); }; const filter$1 = (obj, pred) => { const t = {}; internalFilter(obj, pred, objAcc(t), noop); return t; }; const mapToArray = (obj, f) => { const r = []; each$1(obj, (value, name) => { r.push(f(value, name)); }); return r; }; const values = obj => { return mapToArray(obj, identity); }; const get$c = (obj, key) => { return has$1(obj, key) ? Optional.from(obj[key]) : Optional.none(); }; const has$1 = (obj, key) => hasOwnProperty.call(obj, key); const hasNonNullableKey = (obj, key) => has$1(obj, key) && obj[key] !== undefined && obj[key] !== null; const isEmpty = r => { for (const x in r) { if (hasOwnProperty.call(r, x)) { return false; } } return true; }; const Global = typeof window !== 'undefined' ? window : Function('return this;')(); const path = (parts, scope) => { let o = scope !== undefined && scope !== null ? scope : Global; for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) { o = o[parts[i]]; } return o; }; const resolve$2 = (p, scope) => { const parts = p.split('.'); return path(parts, scope); }; const unsafe = (name, scope) => { return resolve$2(name, scope); }; const getOrDie = (name, scope) => { const actual = unsafe(name, scope); if (actual === undefined || actual === null) { throw new Error(name + ' not available on this browser'); } return actual; }; const getPrototypeOf = Object.getPrototypeOf; const sandHTMLElement = scope => { return getOrDie('HTMLElement', scope); }; const isPrototypeOf = x => { const scope = resolve$2('ownerDocument.defaultView', x); return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf(x).constructor.name)); }; const COMMENT = 8; const DOCUMENT = 9; const DOCUMENT_FRAGMENT = 11; const ELEMENT = 1; const TEXT = 3; const name = element => { const r = element.dom.nodeName; return r.toLowerCase(); }; const type = element => element.dom.nodeType; const isType = t => element => type(element) === t; const isComment = element => type(element) === COMMENT || name(element) === '#comment'; const isHTMLElement = element => isElement(element) && isPrototypeOf(element.dom); const isElement = isType(ELEMENT); const isText = isType(TEXT); const isDocument = isType(DOCUMENT); const isDocumentFragment = isType(DOCUMENT_FRAGMENT); const isTag = tag => e => isElement(e) && name(e) === tag; const rawSet = (dom, key, value) => { if (isString(value) || isBoolean(value) || isNumber(value)) { dom.setAttribute(key, value + ''); } else { console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom); throw new Error('Attribute value was not simple'); } }; const set$2 = (element, key, value) => { rawSet(element.dom, key, value); }; const setAll$1 = (element, attrs) => { const dom = element.dom; each$1(attrs, (v, k) => { rawSet(dom, k, v); }); }; const setOptions = (element, attrs) => { each$1(attrs, (v, k) => { v.fold(() => { remove$7(element, k); }, value => { rawSet(element.dom, k, value); }); }); }; const get$b = (element, key) => { const v = element.dom.getAttribute(key); return v === null ? undefined : v; }; const getOpt = (element, key) => Optional.from(get$b(element, key)); const remove$7 = (element, key) => { element.dom.removeAttribute(key); }; const clone$2 = element => foldl(element.dom.attributes, (acc, attr) => { acc[attr.name] = attr.value; return acc; }, {}); const fromHtml$1 = (html, scope) => { const doc = scope || document; const div = doc.createElement('div'); div.innerHTML = html; if (!div.hasChildNodes() || div.childNodes.length > 1) { const message = 'HTML does not have a single root node'; console.error(message, html); throw new Error(message); } return fromDom$1(div.childNodes[0]); }; const fromTag = (tag, scope) => { const doc = scope || document; const node = doc.createElement(tag); return fromDom$1(node); }; const fromText = (text, scope) => { const doc = scope || document; const node = doc.createTextNode(text); return fromDom$1(node); }; const fromDom$1 = node => { if (node === null || node === undefined) { throw new Error('Node cannot be null or undefined'); } return { dom: node }; }; const fromPoint$1 = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$1); const SugarElement = { fromHtml: fromHtml$1, fromTag, fromText, fromDom: fromDom$1, fromPoint: fromPoint$1 }; const is$2 = (element, selector) => { const dom = element.dom; if (dom.nodeType !== ELEMENT) { return false; } else { const elem = dom; if (elem.matches !== undefined) { return elem.matches(selector); } else if (elem.msMatchesSelector !== undefined) { return elem.msMatchesSelector(selector); } else if (elem.webkitMatchesSelector !== undefined) { return elem.webkitMatchesSelector(selector); } else if (elem.mozMatchesSelector !== undefined) { return elem.mozMatchesSelector(selector); } else { throw new Error('Browser lacks native selectors'); } } }; const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0; const all$1 = (selector, scope) => { const base = scope === undefined ? document : scope.dom; return bypassSelector(base) ? [] : map$1(base.querySelectorAll(selector), SugarElement.fromDom); }; const one = (selector, scope) => { const base = scope === undefined ? document : scope.dom; return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom); }; const eq$1 = (e1, e2) => e1.dom === e2.dom; const contains$1 = (e1, e2) => { const d1 = e1.dom; const d2 = e2.dom; return d1 === d2 ? false : d1.contains(d2); }; const is$1 = is$2; const owner = element => SugarElement.fromDom(element.dom.ownerDocument); const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos); const documentElement = element => SugarElement.fromDom(documentOrOwner(element).dom.documentElement); const defaultView = element => SugarElement.fromDom(documentOrOwner(element).dom.defaultView); const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom); const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom); const parents = (element, isRoot) => { const stop = isFunction(isRoot) ? isRoot : never; let dom = element.dom; const ret = []; while (dom.parentNode !== null && dom.parentNode !== undefined) { const rawParent = dom.parentNode; const p = SugarElement.fromDom(rawParent); ret.push(p); if (stop(p) === true) { break; } else { dom = rawParent; } } return ret; }; const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom); const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom); const children$2 = element => map$1(element.dom.childNodes, SugarElement.fromDom); const child$2 = (element, index) => { const cs = element.dom.childNodes; return Optional.from(cs[index]).map(SugarElement.fromDom); }; const firstChild = element => child$2(element, 0); const before$3 = (marker, element) => { const parent$1 = parent(marker); parent$1.each(v => { v.dom.insertBefore(element.dom, marker.dom); }); }; const after$5 = (marker, element) => { const sibling = nextSibling(marker); sibling.fold(() => { const parent$1 = parent(marker); parent$1.each(v => { append$1(v, element); }); }, v => { before$3(v, element); }); }; const prepend = (parent, element) => { const firstChild$1 = firstChild(parent); firstChild$1.fold(() => { append$1(parent, element); }, v => { parent.dom.insertBefore(element.dom, v.dom); }); }; const append$1 = (parent, element) => { parent.dom.appendChild(element.dom); }; const appendAt = (parent, element, index) => { child$2(parent, index).fold(() => { append$1(parent, element); }, v => { before$3(v, element); }); }; const wrap = (element, wrapper) => { before$3(element, wrapper); append$1(wrapper, element); }; const after$4 = (marker, elements) => { each$2(elements, (x, i) => { const e = i === 0 ? marker : elements[i - 1]; after$5(e, x); }); }; const append = (parent, elements) => { each$2(elements, x => { append$1(parent, x); }); }; const empty = element => { element.dom.textContent = ''; each$2(children$2(element), rogue => { remove$6(rogue); }); }; const remove$6 = element => { const dom = element.dom; if (dom.parentNode !== null) { dom.parentNode.removeChild(dom); } }; const unwrap = wrapper => { const children = children$2(wrapper); if (children.length > 0) { after$4(wrapper, children); } remove$6(wrapper); }; const clone$1 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep)); const shallow = original => clone$1(original, false); const deep = original => clone$1(original, true); const shallowAs = (original, tag) => { const nu = SugarElement.fromTag(tag); const attributes = clone$2(original); setAll$1(nu, attributes); return nu; }; const copy$2 = (original, tag) => { const nu = shallowAs(original, tag); const cloneChildren = children$2(deep(original)); append(nu, cloneChildren); return nu; }; const mutate$1 = (original, tag) => { const nu = shallowAs(original, tag); after$5(original, nu); const children = children$2(original); append(nu, children); remove$6(original); return nu; }; const validSectionList = [ 'tfoot', 'thead', 'tbody', 'colgroup' ]; const isValidSection = parentName => contains$2(validSectionList, parentName); const grid = (rows, columns) => ({ rows, columns }); const address = (row, column) => ({ row, column }); const detail = (element, rowspan, colspan) => ({ element, rowspan, colspan }); const detailnew = (element, rowspan, colspan, isNew) => ({ element, rowspan, colspan, isNew }); const extended = (element, rowspan, colspan, row, column, isLocked) => ({ element, rowspan, colspan, row, column, isLocked }); const rowdetail = (element, cells, section) => ({ element, cells, section }); const rowdetailnew = (element, cells, section, isNew) => ({ element, cells, section, isNew }); const elementnew = (element, isNew, isLocked) => ({ element, isNew, isLocked }); const rowcells = (element, cells, section, isNew) => ({ element, cells, section, isNew }); const bounds = (startRow, startCol, finishRow, finishCol) => ({ startRow, startCol, finishRow, finishCol }); const columnext = (element, colspan, column) => ({ element, colspan, column }); const colgroup = (element, columns) => ({ element, columns }); const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host); const getRootNode = e => SugarElement.fromDom(e.dom.getRootNode()); const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body); const getShadowRoot = e => { const r = getRootNode(e); return isShadowRoot(r) ? Optional.some(r) : Optional.none(); }; const getShadowHost = e => SugarElement.fromDom(e.dom.host); const getOriginalEventTarget = event => { if (isNonNullable(event.target)) { const el = SugarElement.fromDom(event.target); if (isElement(el) && isOpenShadowHost(el)) { if (event.composed && event.composedPath) { const composedPath = event.composedPath(); if (composedPath) { return head(composedPath); } } } } return Optional.from(event.target); }; const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot); const inBody = element => { const dom = isText(element) ? element.dom.parentNode : element.dom; if (dom === undefined || dom === null || dom.ownerDocument === null) { return false; } const doc = dom.ownerDocument; return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost)); }; const body$1 = () => getBody$1(SugarElement.fromDom(document)); const getBody$1 = doc => { const b = doc.dom.body; if (b === null || b === undefined) { throw new Error('Body is not available yet'); } return SugarElement.fromDom(b); }; const ancestors$4 = (scope, predicate, isRoot) => filter$2(parents(scope, isRoot), predicate); const children$1 = (scope, predicate) => filter$2(children$2(scope), predicate); const descendants$1 = (scope, predicate) => { let result = []; each$2(children$2(scope), x => { if (predicate(x)) { result = result.concat([x]); } result = result.concat(descendants$1(x, predicate)); }); return result; }; const ancestors$3 = (scope, selector, isRoot) => ancestors$4(scope, e => is$2(e, selector), isRoot); const children = (scope, selector) => children$1(scope, e => is$2(e, selector)); const descendants = (scope, selector) => all$1(selector, scope); var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => { if (is(scope, a)) { return Optional.some(scope); } else if (isFunction(isRoot) && isRoot(scope)) { return Optional.none(); } else { return ancestor(scope, a, isRoot); } }; const ancestor$2 = (scope, predicate, isRoot) => { let element = scope.dom; const stop = isFunction(isRoot) ? isRoot : never; while (element.parentNode) { element = element.parentNode; const el = SugarElement.fromDom(element); if (predicate(el)) { return Optional.some(el); } else if (stop(el)) { break; } } return Optional.none(); }; const closest$2 = (scope, predicate, isRoot) => { const is = (s, test) => test(s); return ClosestOrAncestor(is, ancestor$2, scope, predicate, isRoot); }; const child$1 = (scope, predicate) => { const pred = node => predicate(SugarElement.fromDom(node)); const result = find$1(scope.dom.childNodes, pred); return result.map(SugarElement.fromDom); }; const descendant$1 = (scope, predicate) => { const descend = node => { for (let i = 0; i < node.childNodes.length; i++) { const child = SugarElement.fromDom(node.childNodes[i]); if (predicate(child)) { return Optional.some(child); } const res = descend(node.childNodes[i]); if (res.isSome()) { return res; } } return Optional.none(); }; return descend(scope.dom); }; const ancestor$1 = (scope, selector, isRoot) => ancestor$2(scope, e => is$2(e, selector), isRoot); const child = (scope, selector) => child$1(scope, e => is$2(e, selector)); const descendant = (scope, selector) => one(selector, scope); const closest$1 = (scope, selector, isRoot) => { const is = (element, selector) => is$2(element, selector); return ClosestOrAncestor(is, ancestor$1, scope, selector, isRoot); }; const is = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs)); const cat = arr => { const r = []; const push = x => { r.push(x); }; for (let i = 0; i < arr.length; i++) { arr[i].each(push); } return r; }; const bindFrom = (a, f) => a !== undefined && a !== null ? f(a) : Optional.none(); const someIf = (b, a) => b ? Optional.some(a) : Optional.none(); const removeFromStart = (str, numChars) => { return str.substring(numChars); }; const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr; const removeLeading = (str, prefix) => { return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str; }; const contains = (str, substr, start = 0, end) => { const idx = str.indexOf(substr, start); if (idx !== -1) { return isUndefined(end) ? true : idx + substr.length <= end; } else { return false; } }; const startsWith = (str, prefix) => { return checkRange(str, prefix, 0); }; const endsWith = (str, suffix) => { return checkRange(str, suffix, str.length - suffix.length); }; const blank = r => s => s.replace(r, ''); const trim = blank(/^\s+|\s+$/g); const isNotEmpty = s => s.length > 0; const toFloat = value => { const num = parseFloat(value); return isNaN(num) ? Optional.none() : Optional.some(num); }; const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue); const internalSet = (dom, property, value) => { if (!isString(value)) { console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom); throw new Error('CSS value must be a string: ' + value); } if (isSupported(dom)) { dom.style.setProperty(property, value); } }; const internalRemove = (dom, property) => { if (isSupported(dom)) { dom.style.removeProperty(property); } }; const set$1 = (element, property, value) => { const dom = element.dom; internalSet(dom, property, value); }; const setAll = (element, css) => { const dom = element.dom; each$1(css, (v, k) => { internalSet(dom, k, v); }); }; const get$a = (element, property) => { const dom = element.dom; const styles = window.getComputedStyle(dom); const r = styles.getPropertyValue(property); return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r; }; const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : ''; const getRaw$2 = (element, property) => { const dom = element.dom; const raw = getUnsafeProperty(dom, property); return Optional.from(raw).filter(r => r.length > 0); }; const remove$5 = (element, property) => { const dom = element.dom; internalRemove(dom, property); if (is(getOpt(element, 'style').map(trim), '')) { remove$7(element, 'style'); } }; const copy$1 = (source, target) => { const sourceDom = source.dom; const targetDom = target.dom; if (isSupported(sourceDom) && isSupported(targetDom)) { targetDom.style.cssText = sourceDom.style.cssText; } }; const getAttrValue = (cell, name, fallback = 0) => getOpt(cell, name).map(value => parseInt(value, 10)).getOr(fallback); const getSpan = (cell, type) => getAttrValue(cell, type, 1); const hasColspan = cellOrCol => { if (isTag('col')(cellOrCol)) { return getAttrValue(cellOrCol, 'span', 1) > 1; } else { return getSpan(cellOrCol, 'colspan') > 1; } }; const hasRowspan = cell => getSpan(cell, 'rowspan') > 1; const getCssValue = (element, property) => parseInt(get$a(element, property), 10); const minWidth = constant(10); const minHeight = constant(10); const firstLayer = (scope, selector) => { return filterFirstLayer(scope, selector, always); }; const filterFirstLayer = (scope, selector, predicate) => { return bind$2(children$2(scope), x => { if (is$2(x, selector)) { return predicate(x) ? [x] : []; } else { return filterFirstLayer(x, selector, predicate); } }); }; const lookup = (tags, element, isRoot = never) => { if (isRoot(element)) { return Optional.none(); } if (contains$2(tags, name(element))) { return Optional.some(element); } const isRootOrUpperTable = elm => is$2(elm, 'table') || isRoot(elm); return ancestor$1(element, tags.join(','), isRootOrUpperTable); }; const cell = (element, isRoot) => lookup([ 'td', 'th' ], element, isRoot); const cells$1 = ancestor => firstLayer(ancestor, 'th,td'); const columns$1 = ancestor => { if (is$2(ancestor, 'colgroup')) { return children(ancestor, 'col'); } else { return bind$2(columnGroups(ancestor), columnGroup => children(columnGroup, 'col')); } }; const table = (element, isRoot) => closest$1(element, 'table', isRoot); const rows$1 = ancestor => firstLayer(ancestor, 'tr'); const columnGroups = ancestor => table(ancestor).fold(constant([]), table => children(table, 'colgroup')); const fromRowsOrColGroups = (elems, getSection) => map$1(elems, row => { if (name(row) === 'colgroup') { const cells = map$1(columns$1(row), column => { const colspan = getAttrValue(column, 'span', 1); return detail(column, 1, colspan); }); return rowdetail(row, cells, 'colgroup'); } else { const cells = map$1(cells$1(row), cell => { const rowspan = getAttrValue(cell, 'rowspan', 1); const colspan = getAttrValue(cell, 'colspan', 1); return detail(cell, rowspan, colspan); }); return rowdetail(row, cells, getSection(row)); } }); const getParentSection = group => parent(group).map(parent => { const parentName = name(parent); return isValidSection(parentName) ? parentName : 'tbody'; }).getOr('tbody'); const fromTable$1 = table => { const rows = rows$1(table); const columnGroups$1 = columnGroups(table); const elems = [ ...columnGroups$1, ...rows ]; return fromRowsOrColGroups(elems, getParentSection); }; const fromPastedRows = (elems, section) => fromRowsOrColGroups(elems, () => section); const cached = f => { let called = false; let r; return (...args) => { if (!called) { called = true; r = f.apply(null, args); } return r; }; }; const DeviceType = (os, browser, userAgent, mediaMatch) => { const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true; const isiPhone = os.isiOS() && !isiPad; const isMobile = os.isiOS() || os.isAndroid(); const isTouch = isMobile || mediaMatch('(pointer:coarse)'); const isTablet = isiPad || !isiPhone && isMobile && mediaMatch('(min-device-width:768px)'); const isPhone = isiPhone || isMobile && !isTablet; const iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false; const isDesktop = !isPhone && !isTablet && !iOSwebview; return { isiPad: constant(isiPad), isiPhone: constant(isiPhone), isTablet: constant(isTablet), isPhone: constant(isPhone), isTouch: constant(isTouch), isAndroid: os.isAndroid, isiOS: os.isiOS, isWebView: constant(iOSwebview), isDesktop: constant(isDesktop) }; }; const firstMatch = (regexes, s) => { for (let i = 0; i < regexes.length; i++) { const x = regexes[i]; if (x.test(s)) { return x; } } return undefined; }; const find = (regexes, agent) => { const r = firstMatch(regexes, agent); if (!r) { return { major: 0, minor: 0 }; } const group = i => { return Number(agent.replace(r, '$' + i)); }; return nu$2(group(1), group(2)); }; const detect$5 = (versionRegexes, agent) => { const cleanedAgent = String(agent).toLowerCase(); if (versionRegexes.length === 0) { return unknown$2(); } return find(versionRegexes, cleanedAgent); }; const unknown$2 = () => { return nu$2(0, 0); }; const nu$2 = (major, minor) => { return { major, minor }; }; const Version = { nu: nu$2, detect: detect$5, unknown: unknown$2 }; const detectBrowser$1 = (browsers, userAgentData) => { return findMap(userAgentData.brands, uaBrand => { const lcBrand = uaBrand.brand.toLowerCase(); return find$1(browsers, browser => { var _a; return lcBrand === ((_a = browser.brand) === null || _a === void 0 ? void 0 : _a.toLowerCase()); }).map(info => ({ current: info.name, version: Version.nu(parseInt(uaBrand.version, 10), 0) })); }); }; const detect$4 = (candidates, userAgent) => { const agent = String(userAgent).toLowerCase(); return find$1(candidates, candidate => { return candidate.search(agent); }); }; const detectBrowser = (browsers, userAgent) => { return detect$4(browsers, userAgent).map(browser => { const version = Version.detect(browser.versionRegexes, userAgent); return { current: browser.name, version }; }); }; const detectOs = (oses, userAgent) => { return detect$4(oses, userAgent).map(os => { const version = Version.detect(os.versionRegexes, userAgent); return { current: os.name, version }; }); }; const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/; const checkContains = target => { return uastring => { return contains(uastring, target); }; }; const browsers = [ { name: 'Edge', versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/], search: uastring => { return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit'); } }, { name: 'Chromium', brand: 'Chromium', versionRegexes: [ /.*?chrome\/([0-9]+)\.([0-9]+).*/, normalVersionRegex ], search: uastring => { return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe'); } }, { name: 'IE', versionRegexes: [ /.*?msie\ ?([0-9]+)\.([0-9]+).*/, /.*?rv:([0-9]+)\.([0-9]+).*/ ], search: uastring => { return contains(uastring, 'msie') || contains(uastring, 'trident'); } }, { name: 'Opera', versionRegexes: [ normalVersionRegex, /.*?opera\/([0-9]+)\.([0-9]+).*/ ], search: checkContains('opera') }, { name: 'Firefox', versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/], search: checkContains('firefox') }, { name: 'Safari', versionRegexes: [ normalVersionRegex, /.*?cpu os ([0-9]+)_([0-9]+).*/ ], search: uastring => { return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit'); } } ]; const oses = [ { name: 'Windows', search: checkContains('win'), versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/] }, { name: 'iOS', search: uastring => { return contains(uastring, 'iphone') || contains(uastring, 'ipad'); }, versionRegexes: [ /.*?version\/\ ?([0-9]+)\.([0-9]+).*/, /.*cpu os ([0-9]+)_([0-9]+).*/, /.*cpu iphone os ([0-9]+)_([0-9]+).*/ ] }, { name: 'Android', search: checkContains('android'), versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/] }, { name: 'macOS', search: checkContains('mac os x'), versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/] }, { name: 'Linux', search: checkContains('linux'), versionRegexes: [] }, { name: 'Solaris', search: checkContains('sunos'), versionRegexes: [] }, { name: 'FreeBSD', search: checkContains('freebsd'), versionRegexes: [] }, { name: 'ChromeOS', search: checkContains('cros'), versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/] } ]; const PlatformInfo = { browsers: constant(browsers), oses: constant(oses) }; const edge = 'Edge'; const chromium = 'Chromium'; const ie = 'IE'; const opera = 'Opera'; const firefox = 'Firefox'; const safari = 'Safari'; const unknown$1 = () => { return nu$1({ current: undefined, version: Version.unknown() }); }; const nu$1 = info => { const current = info.current; const version = info.version; const isBrowser = name => () => current === name; return { current, version, isEdge: isBrowser(edge), isChromium: isBrowser(chromium), isIE: isBrowser(ie), isOpera: isBrowser(opera), isFirefox: isBrowser(firefox), isSafari: isBrowser(safari) }; }; const Browser = { unknown: unknown$1, nu: nu$1, edge: constant(edge), chromium: constant(chromium), ie: constant(ie), opera: constant(opera), firefox: constant(firefox), safari: constant(safari) }; const windows = 'Windows'; const ios = 'iOS'; const android = 'Android'; const linux = 'Linux'; const macos = 'macOS'; const solaris = 'Solaris'; const freebsd = 'FreeBSD'; const chromeos = 'ChromeOS'; const unknown = () => { return nu({ current: undefined, version: Version.unknown() }); }; const nu = info => { const current = info.current; const version = info.version; const isOS = name => () => current === name; return { current, version, isWindows: isOS(windows), isiOS: isOS(ios), isAndroid: isOS(android), isMacOS: isOS(macos), isLinux: isOS(linux), isSolaris: isOS(solaris), isFreeBSD: isOS(freebsd), isChromeOS: isOS(chromeos) }; }; const OperatingSystem = { unknown, nu, windows: constant(windows), ios: constant(ios), android: constant(android), linux: constant(linux), macos: constant(macos), solaris: constant(solaris), freebsd: constant(freebsd), chromeos: constant(chromeos) }; const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => { const browsers = PlatformInfo.browsers(); const oses = PlatformInfo.oses(); const browser = userAgentDataOpt.bind(userAgentData => detectBrowser$1(browsers, userAgentData)).orThunk(() => detectBrowser(browsers, userAgent)).fold(Browser.unknown, Browser.nu); const os = detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu); const deviceType = DeviceType(os, browser, userAgent, mediaMatch); return { browser, os, deviceType }; }; const PlatformDetection = { detect: detect$3 }; const mediaMatch = query => window.matchMedia(query).matches; let platform = cached(() => PlatformDetection.detect(window.navigator.userAgent, Optional.from(window.navigator.userAgentData), mediaMatch)); const detect$2 = () => platform(); const Dimension = (name, getOffset) => { const set = (element, h) => { if (!isNumber(h) && !h.match(/^[0-9]+$/)) { throw new Error(name + '.set accepts only positive integer values. Value was ' + h); } const dom = element.dom; if (isSupported(dom)) { dom.style[name] = h + 'px'; } }; const get = element => { const r = getOffset(element); if (r <= 0 || r === null) { const css = get$a(element, name); return parseFloat(css) || 0; } return r; }; const getOuter = get; const aggregate = (element, properties) => foldl(properties, (acc, property) => { const val = get$a(element, property); const value = val === undefined ? 0 : parseInt(val, 10); return isNaN(value) ? acc : acc + value; }, 0); const max = (element, value, properties) => { const cumulativeInclusions = aggregate(element, properties); const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0; return absoluteMax; }; return { set, get, getOuter, aggregate, max }; }; const toNumber = (px, fallback) => toFloat(px).getOr(fallback); const getProp = (element, name, fallback) => toNumber(get$a(element, name), fallback); const calcContentBoxSize = (element, size, upper, lower) => { const paddingUpper = getProp(element, `padding-${ upper }`, 0); const paddingLower = getProp(element, `padding-${ lower }`, 0); const borderUpper = getProp(element, `border-${ upper }-width`, 0); const borderLower = getProp(element, `border-${ lower }-width`, 0); return size - paddingUpper - paddingLower - borderUpper - borderLower; }; const getCalculatedWidth = (element, boxSizing) => { const dom = element.dom; const width = dom.getBoundingClientRect().width || dom.offsetWidth; return boxSizing === 'border-box' ? width : calcContentBoxSize(element, width, 'left', 'right'); }; const getHeight$1 = element => getProp(element, 'height', element.dom.offsetHeight); const getWidth = element => getProp(element, 'width', element.dom.offsetWidth); const getInnerWidth = element => getCalculatedWidth(element, 'content-box'); const api$2 = Dimension('width', element => element.dom.offsetWidth); const get$9 = element => api$2.get(element); const getOuter$2 = element => api$2.getOuter(element); const getInner = getInnerWidth; const getRuntime$1 = getWidth; const addCells = (gridRow, index, cells) => { const existingCells = gridRow.cells; const before = existingCells.slice(0, index); const after = existingCells.slice(index); const newCells = before.concat(cells).concat(after); return setCells(gridRow, newCells); }; const addCell = (gridRow, index, cell) => addCells(gridRow, index, [cell]); const mutateCell = (gridRow, index, cell) => { const cells = gridRow.cells; cells[index] = cell; }; const setCells = (gridRow, cells) => rowcells(gridRow.element, cells, gridRow.section, gridRow.isNew); const mapCells = (gridRow, f) => { const cells = gridRow.cells; const r = map$1(cells, f); return rowcells(gridRow.element, r, gridRow.section, gridRow.isNew); }; const getCell = (gridRow, index) => gridRow.cells[index]; const getCellElement = (gridRow, index) => getCell(gridRow, index).element; const cellLength = gridRow => gridRow.cells.length; const extractGridDetails = grid => { const result = partition(grid, row => row.section === 'colgroup'); return { rows: result.fail, cols: result.pass }; }; const clone = (gridRow, cloneRow, cloneCell) => { const newCells = map$1(gridRow.cells, cloneCell); return rowcells(cloneRow(gridRow.element), newCells, gridRow.section, true); }; const LOCKED_COL_ATTR = 'data-snooker-locked-cols'; const getLockedColumnsFromTable = table => getOpt(table, LOCKED_COL_ATTR).bind(lockedColStr => Optional.from(lockedColStr.match(/\d+/g))).map(lockedCols => mapToObject(lockedCols, always)); const getLockedColumnsFromGrid = grid => { const locked = foldl(extractGridDetails(grid).rows, (acc, row) => { each$2(row.cells, (cell, idx) => { if (cell.isLocked) { acc[idx] = true; } }); return acc; }, {}); const lockedArr = mapToArray(locked, (_val, key) => parseInt(key, 10)); return sort$1(lockedArr); }; const key = (row, column) => { return row + ',' + column; }; const getAt = (warehouse, row, column) => Optional.from(warehouse.access[key(row, column)]); const findItem = (warehouse, item, comparator) => { const filtered = filterItems(warehouse, detail => { return comparator(item, detail.element); }); return filtered.length > 0 ? Optional.some(filtered[0]) : Optional.none(); }; const filterItems = (warehouse, predicate) => { const all = bind$2(warehouse.all, r => { return r.cells; }); return filter$2(all, predicate); }; const generateColumns = rowData => { const columnsGroup = {}; let index = 0; each$2(rowData.cells, column => { const colspan = column.colspan; range$1(colspan, columnIndex => { const colIndex = index + columnIndex; columnsGroup[colIndex] = columnext(column.element, colspan, colIndex); }); index += colspan; }); return columnsGroup; }; const generate$2 = list => { const access = {}; const cells = []; const tableOpt = head(list).map(rowData => rowData.element).bind(table); const lockedColumns = tableOpt.bind(getLockedColumnsFromTable).getOr({}); let maxRows = 0; let maxColumns = 0; let rowCount = 0; const { pass: colgroupRows, fail: rows } = partition(list, rowData => rowData.section === 'colgroup'); each$2(rows, rowData => { const currentRow = []; each$2(rowData.cells, rowCell => { let start = 0; while (access[key(rowCount, start)] !== undefined) { start++; } const isLocked = hasNonNullableKey(lockedColumns, start.toString()); const current = extended(rowCell.element, rowCell.rowspan, rowCell.colspan, rowCount, start, isLocked); for (let occupiedColumnPosition = 0; occupiedColumnPosition < rowCell.colspan; occupiedColumnPosition++) { for (let occupiedRowPosition = 0; occupiedRowPosition < rowCell.rowspan; occupiedRowPosition++) { const rowPosition = rowCount + occupiedRowPosition; const columnPosition = start + occupiedColumnPosition; const newpos = key(rowPosition, columnPosition); access[newpos] = current; maxColumns = Math.max(maxColumns, columnPosition + 1); } } currentRow.push(current); }); maxRows++; cells.push(rowdetail(rowData.element, currentRow, rowData.section)); rowCount++; }); const {columns, colgroups} = last$2(colgroupRows).map(rowData => { const columns = generateColumns(rowData); const colgroup$1 = colgroup(rowData.element, values(columns)); return { colgroups: [colgroup$1], columns }; }).getOrThunk(() => ({ colgroups: [], columns: {} })); const grid$1 = grid(maxRows, maxColumns); return { grid: grid$1, access, all: cells, columns, colgroups }; }; const fromTable = table => { const list = fromTable$1(table); return generate$2(list); }; const justCells = warehouse => bind$2(warehouse.all, w => w.cells); const justColumns = warehouse => values(warehouse.columns); const hasColumns = warehouse => keys(warehouse.columns).length > 0; const getColumnAt = (warehouse, columnIndex) => Optional.from(warehouse.columns[columnIndex]); const Warehouse = { fromTable, generate: generate$2, getAt, findItem, filterItems, justCells, justColumns, hasColumns, getColumnAt }; const columns = (warehouse, isValidCell = always) => { const grid = warehouse.grid; const cols = range$1(grid.columns, identity); const rowsArr = range$1(grid.rows, identity); return map$1(cols, col => { const getBlock = () => bind$2(rowsArr, r => Warehouse.getAt(warehouse, r, col).filter(detail => detail.column === col).toArray()); const isValid = detail => detail.colspan === 1 && isValidCell(detail.element); const getFallback = () => Warehouse.getAt(warehouse, 0, col); return decide(getBlock, isValid, getFallback); }); }; const decide = (getBlock, isValid, getFallback) => { const inBlock = getBlock(); const validInBlock = find$1(inBlock, isValid); const detailOption = validInBlock.orThunk(() => Optional.from(inBlock[0]).orThunk(getFallback)); return detailOption.map(detail => detail.element); }; const rows = warehouse => { const grid = warehouse.grid; const rowsArr = range$1(grid.rows, identity); const cols = range$1(grid.columns, identity); return map$1(rowsArr, row => { const getBlock = () => bind$2(cols, c => Warehouse.getAt(warehouse, row, c).filter(detail => detail.row === row).fold(constant([]), detail => [detail])); const isSingle = detail => detail.rowspan === 1; const getFallback = () => Warehouse.getAt(warehouse, row, 0); return decide(getBlock, isSingle, getFallback); }); }; const deduce = (xs, index) => { if (index < 0 || index >= xs.length - 1) { return Optional.none(); } const current = xs[index].fold(() => { const rest = reverse(xs.slice(0, index)); return findMap(rest, (a, i) => a.map(aa => ({ value: aa, delta: i + 1 }))); }, c => Optional.some({ value: c, delta: 0 })); const next = xs[index + 1].fold(() => { const rest = xs.slice(index + 1); return findMap(rest, (a, i) => a.map(aa => ({ value: aa, delta: i + 1 }))); }, n => Optional.some({ value: n, delta: 1 })); return current.bind(c => next.map(n => { const extras = n.delta + c.delta; return Math.abs(n.value - c.value) / extras; })); }; const onDirection = (isLtr, isRtl) => element => getDirection(element) === 'rtl' ? isRtl : isLtr; const getDirection = element => get$a(element, 'direction') === 'rtl' ? 'rtl' : 'ltr'; const api$1 = Dimension('height', element => { const dom = element.dom; return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight; }); const get$8 = element => api$1.get(element); const getOuter$1 = element => api$1.getOuter(element); const getRuntime = getHeight$1; const r = (left, top) => { const translate = (x, y) => r(left + x, top + y); return { left, top, translate }; }; const SugarPosition = r; const boxPosition = dom => { const box = dom.getBoundingClientRect(); return SugarPosition(box.left, box.top); }; const firstDefinedOrZero = (a, b) => { if (a !== undefined) { return a; } else { return b !== undefined ? b : 0; } }; const absolute = element => { const doc = element.dom.ownerDocument; const body = doc.body; const win = doc.defaultView; const html = doc.documentElement; if (body === element.dom) { return SugarPosition(body.offsetLeft, body.offsetTop); } const scrollTop = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageYOffset, html.scrollTop); const scrollLeft = firstDefinedOrZero(win === null || win === void 0 ? void 0 : win.pageXOffset, html.scrollLeft); const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop); const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft); return viewport(element).translate(scrollLeft - clientLeft, scrollTop - clientTop); }; const viewport = element => { const dom = element.dom; const doc = dom.ownerDocument; const body = doc.body; if (body === dom) { return SugarPosition(body.offsetLeft, body.offsetTop); } if (!inBody(element)) { return SugarPosition(0, 0); } return boxPosition(dom); }; const rowInfo = (row, y) => ({ row, y }); const colInfo = (col, x) => ({ col, x }); const rtlEdge = cell => { const pos = absolute(cell); return pos.left + getOuter$2(cell); }; const ltrEdge = cell => { return absolute(cell).left; }; const getLeftEdge = (index, cell) => { return colInfo(index, ltrEdge(cell)); }; const getRightEdge = (index, cell) => { return colInfo(index, rtlEdge(cell)); }; const getTop$1 = cell => { return absolute(cell).top; }; const getTopEdge = (index, cell) => { return rowInfo(index, getTop$1(cell)); }; const getBottomEdge = (index, cell) => { return rowInfo(index, getTop$1(cell) + getOuter$1(cell)); }; const findPositions = (getInnerEdge, getOuterEdge, array) => { if (array.length === 0) { return []; } const lines = map$1(array.slice(1), (cellOption, index) => { return cellOption.map(cell => { return getInnerEdge(index, cell); }); }); const lastLine = array[array.length - 1].map(cell => { return getOuterEdge(array.length - 1, cell); }); return lines.concat([lastLine]); }; const negate = step => { return -step; }; const height = { delta: identity, positions: optElements => findPositions(getTopEdge, getBottomEdge, optElements), edge: getTop$1 }; const ltr$1 = { delta: identity, edge: ltrEdge, positions: optElements => findPositions(getLeftEdge, getRightEdge, optElements) }; const rtl$1 = { delta: negate, edge: rtlEdge, positions: optElements => findPositions(getRightEdge, getLeftEdge, optElements) }; const detect$1 = onDirection(ltr$1, rtl$1); const width = { delta: (amount, table) => detect$1(table).delta(amount, table), positions: (cols, table) => detect$1(table).positions(cols, table), edge: cell => detect$1(cell).edge(cell) }; const units = { unsupportedLength: [ 'em', 'ex', 'cap', 'ch', 'ic', 'rem', 'lh', 'rlh', 'vw', 'vh', 'vi', 'vb', 'vmin', 'vmax', 'cm', 'mm', 'Q', 'in', 'pc', 'pt', 'px' ], fixed: [ 'px', 'pt' ], relative: ['%'], empty: [''] }; const pattern = (() => { const decimalDigits = '[0-9]+'; const signedInteger = '[+-]?' + decimalDigits; const exponentPart = '[eE]' + signedInteger; const dot = '\\.'; const opt = input => `(?:${ input })?`; const unsignedDecimalLiteral = [ 'Infinity', decimalDigits + dot + opt(decimalDigits) + opt(exponentPart), dot + decimalDigits + opt(exponentPart), decimalDigits + opt(exponentPart) ].join('|'); const float = `[+-]?(?:${ unsignedDecimalLiteral })`; return new RegExp(`^(${ float })(.*)$`); })(); const isUnit = (unit, accepted) => exists(accepted, acc => exists(units[acc], check => unit === check)); const parse = (input, accepted) => { const match = Optional.from(pattern.exec(input)); return match.bind(array => { const value = Number(array[1]); const unitRaw = array[2]; if (isUnit(unitRaw, accepted)) { return Optional.some({ value, unit: unitRaw }); } else { return Optional.none(); } }); }; const rPercentageBasedSizeRegex = /(\d+(\.\d+)?)%/; const rPixelBasedSizeRegex = /(\d+(\.\d+)?)px|em/; const isCol$2 = isTag('col'); const isRow$2 = isTag('tr'); const getPercentSize = (elm, outerGetter, innerGetter) => { const relativeParent = parentElement(elm).getOrThunk(() => getBody$1(owner(elm))); return outerGetter(elm) / innerGetter(relativeParent) * 100; }; const setPixelWidth = (cell, amount) => { set$1(cell, 'width', amount + 'px'); }; const setPercentageWidth = (cell, amount) => { set$1(cell, 'width', amount + '%'); }; const setHeight = (cell, amount) => { set$1(cell, 'height', amount + 'px'); }; const removeHeight = cell => { remove$5(cell, 'height'); }; const getHeightValue = cell => getRuntime(cell) + 'px'; const convert = (cell, number, getter, setter) => { const newSize = table(cell).map(table => { const total = getter(table); return Math.floor(number / 100 * total); }).getOr(number); setter(cell, newSize); return newSize; }; const normalizePixelSize = (value, cell, getter, setter) => { const number = parseFloat(value); return endsWith(value, '%') && name(cell) !== 'table' ? convert(cell, number, getter, setter) : number; }; const getTotalHeight = cell => { const value = getHeightValue(cell); if (!value) { return get$8(cell); } return normalizePixelSize(value, cell, get$8, setHeight); }; const get$7 = (cell, type, f) => { const v = f(cell); const span = getSpan(cell, type); return v / span; }; const getRaw$1 = (element, prop) => { return getRaw$2(element, prop).orThunk(() => { return getOpt(element, prop).map(val => val + 'px'); }); }; const getRawWidth$1 = element => getRaw$1(element, 'width'); const getRawHeight$1 = element => getRaw$1(element, 'height'); const getPercentageWidth = cell => getPercentSize(cell, get$9, getInner); const getPixelWidth$1 = cell => isCol$2(cell) ? get$9(cell) : getRuntime$1(cell); const getHeight = cell => { return isRow$2(cell) ? get$8(cell) : get$7(cell, 'rowspan', getTotalHeight); }; const getGenericWidth = cell => { const width = getRawWidth$1(cell); return width.bind(w => parse(w, [ 'fixed', 'relative', 'empty' ])); }; const setGenericWidth = (cell, amount, unit) => { set$1(cell, 'width', amount + unit); }; const getPixelTableWidth = table => get$9(table) + 'px'; const getPixelTableHeight = table => get$8(table) + 'px'; const getPercentTableWidth = table => getPercentSize(table, get$9, getInner) + '%'; const isPercentSizing$1 = table => getRawWidth$1(table).exists(size => rPercentageBasedSizeRegex.test(size)); const isPixelSizing$1 = table => getRawWidth$1(table).exists(size => rPixelBasedSizeRegex.test(size)); const isNoneSizing$1 = table => getRawWidth$1(table).isNone(); const percentageBasedSizeRegex = constant(rPercentageBasedSizeRegex); const isCol$1 = isTag('col'); const getRawW = cell => { return getRawWidth$1(cell).getOrThunk(() => getPixelWidth$1(cell) + 'px'); }; const getRawH = cell => { return getRawHeight$1(cell).getOrThunk(() => getHeight(cell) + 'px'); }; const justCols = warehouse => map$1(Warehouse.justColumns(warehouse), column => Optional.from(column.element)); const isValidColumn = cell => { const browser = detect$2().browser; const supportsColWidths = browser.isChromium() || browser.isFirefox(); return isCol$1(cell) ? supportsColWidths : true; }; const getDimension = (cellOpt, index, backups, filter, getter, fallback) => cellOpt.filter(filter).fold(() => fallback(deduce(backups, index)), cell => getter(cell)); const getWidthFrom = (warehouse, table, getWidth, fallback) => { const columnCells = columns(warehouse); const columns$1 = Warehouse.hasColumns(warehouse) ? justCols(warehouse) : columnCells; const backups = [Optional.some(width.edge(table))].concat(map$1(width.positions(columnCells, table), pos => pos.map(p => p.x))); const colFilter = not(hasColspan); return map$1(columns$1, (cellOption, c) => { return getDimension(cellOption, c, backups, colFilter, column => { if (isValidColumn(column)) { return getWidth(column); } else { const cell = bindFrom(columnCells[c], identity); return getDimension(cell, c, backups, colFilter, cell => fallback(Optional.some(get$9(cell))), fallback); } }, fallback); }); }; const getDeduced = deduced => { return deduced.map(d => { return d + 'px'; }).getOr(''); }; const getRawWidths = (warehouse, table) => { return getWidthFrom(warehouse, table, getRawW, getDeduced); }; const getPercentageWidths = (warehouse, table, tableSize) => { return getWidthFrom(warehouse, table, getPercentageWidth, deduced => { return deduced.fold(() => { return tableSize.minCellWidth(); }, cellWidth => { return cellWidth / tableSize.pixelWidth() * 100; }); }); }; const getPixelWidths = (warehouse, table, tableSize) => { return getWidthFrom(warehouse, table, getPixelWidth$1, deduced => { return deduced.getOrThunk(tableSize.minCellWidth); }); }; const getHeightFrom = (warehouse, table, getHeight, fallback) => { const rowCells = rows(warehouse); const rows$1 = map$1(warehouse.all, r => Optional.some(r.element)); const backups = [Optional.some(height.edge(table))].concat(map$1(height.positions(rowCells, table), pos => pos.map(p => p.y))); return map$1(rows$1, (row, i) => getDimension(row, i, backups, always, getHeight, fallback)); }; const getPixelHeights = (warehouse, table) => { return getHeightFrom(warehouse, table, getHeight, deduced => { return deduced.getOrThunk(minHeight); }); }; const getRawHeights = (warehouse, table) => { return getHeightFrom(warehouse, table, getRawH, getDeduced); }; const widthLookup = (table, getter) => () => { if (inBody(table)) { return getter(table); } else { return parseFloat(getRaw$2(table, 'width').getOr('0')); } }; const noneSize = table => { const getWidth = widthLookup(table, get$9); const zero = constant(0); const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize); return { width: getWidth, pixelWidth: getWidth, getWidths, getCellDelta: zero, singleColumnWidth: constant([0]), minCellWidth: zero, setElementWidth: noop, adjustTableWidth: noop, isRelative: true, label: 'none' }; }; const percentageSize = table => { const getFloatWidth = widthLookup(table, elem => parseFloat(getPercentTableWidth(elem))); const getWidth = widthLookup(table, get$9); const getCellDelta = delta => delta / getWidth() * 100; const singleColumnWidth = (w, _delta) => [100 - w]; const minCellWidth = () => minWidth() / getWidth() * 100; const adjustTableWidth = delta => { const currentWidth = getFloatWidth(); const change = delta / 100 * currentWidth; const newWidth = currentWidth + change; setPercentageWidth(table, newWidth); }; const getWidths = (warehouse, tableSize) => getPercentageWidths(warehouse, table, tableSize); return { width: getFloatWidth, pixelWidth: getWidth, getWidths, getCellDelta, singleColumnWidth, minCellWidth, setElementWidth: setPercentageWidth, adjustTableWidth, isRelative: true, label: 'percent' }; }; const pixelSize = table => { const getWidth = widthLookup(table, get$9); const getCellDelta = identity; const singleColumnWidth = (w, delta) => { const newNext = Math.max(minWidth(), w + delta); return [newNext - w]; }; const adjustTableWidth = delta => { const newWidth = getWidth() + delta; setPixelWidth(table, newWidth); }; const getWidths = (warehouse, tableSize) => getPixelWidths(warehouse, table, tableSize); return { width: getWidth, pixelWidth: getWidth, getWidths, getCellDelta, singleColumnWidth, minCellWidth: minWidth, setElementWidth: setPixelWidth, adjustTableWidth, isRelative: false, label: 'pixel' }; }; const chooseSize = (element, width) => { const percentMatch = percentageBasedSizeRegex().exec(width); if (percentMatch !== null) { return percentageSize(element); } else { return pixelSize(element); } }; const getTableSize = table => { const width = getRawWidth$1(table); return width.fold(() => noneSize(table), w => chooseSize(table, w)); }; const TableSize = { getTableSize, pixelSize, percentageSize, noneSize }; const statsStruct = (minRow, minCol, maxRow, maxCol, allCells, selectedCells) => ({ minRow, minCol, maxRow, maxCol, allCells, selectedCells }); const findSelectedStats = (house, isSelected) => { const totalColumns = house.grid.columns; const totalRows = house.grid.rows; let minRow = totalRows; let minCol = totalColumns; let maxRow = 0; let maxCol = 0; const allCells = []; const selectedCells = []; each$1(house.access, detail => { allCells.push(detail); if (isSelected(detail)) { selectedCells.push(detail); const startRow = detail.row; const endRow = startRow + detail.rowspan - 1; const startCol = detail.column; const endCol = startCol + detail.colspan - 1; if (startRow < minRow) { minRow = startRow; } else if (endRow > maxRow) { maxRow = endRow; } if (startCol < minCol) { minCol = startCol; } else if (endCol > maxCol) { maxCol = endCol; } } }); return statsStruct(minRow, minCol, maxRow, maxCol, allCells, selectedCells); }; const makeCell = (list, seenSelected, rowIndex) => { const row = list[rowIndex].element; const td = SugarElement.fromTag('td'); append$1(td, SugarElement.fromTag('br')); const f = seenSelected ? append$1 : prepend; f(row, td); }; const fillInGaps = (list, house, stats, isSelected) => { const rows = filter$2(list, row => row.section !== 'colgroup'); const totalColumns = house.grid.columns; const totalRows = house.grid.rows; for (let i = 0; i < totalRows; i++) { let seenSelected = false; for (let j = 0; j < totalColumns; j++) { if (!(i < stats.minRow || i > stats.maxRow || j < stats.minCol || j > stats.maxCol)) { const needCell = Warehouse.getAt(house, i, j).filter(isSelected).isNone(); if (needCell) { makeCell(rows, seenSelected, i); } else { seenSelected = true; } } } } }; const clean = (replica, stats, house, widthDelta) => { each$1(house.columns, col => { if (col.column < stats.minCol || col.column > stats.maxCol) { remove$6(col.element); } }); const emptyRows = filter$2(firstLayer(replica, 'tr'), row => row.dom.childElementCount === 0); each$2(emptyRows, remove$6); if (stats.minCol === stats.maxCol || stats.minRow === stats.maxRow) { each$2(firstLayer(replica, 'th,td'), cell => { remove$7(cell, 'rowspan'); remove$7(cell, 'colspan'); }); } remove$7(replica, LOCKED_COL_ATTR); remove$7(replica, 'data-snooker-col-series'); const tableSize = TableSize.getTableSize(replica); tableSize.adjustTableWidth(widthDelta); }; const getTableWidthDelta = (table, warehouse, tableSize, stats) => { if (stats.minCol === 0 && warehouse.grid.columns === stats.maxCol + 1) { return 0; } const colWidths = getPixelWidths(warehouse, table, tableSize); const allColsWidth = foldl(colWidths, (acc, width) => acc + width, 0); const selectedColsWidth = foldl(colWidths.slice(stats.minCol, stats.maxCol + 1), (acc, width) => acc + width, 0); const newWidth = selectedColsWidth / allColsWidth * tableSize.pixelWidth(); const delta = newWidth - tableSize.pixelWidth(); return tableSize.getCellDelta(delta); }; const extract$1 = (table, selectedSelector) => { const isSelected = detail => is$2(detail.element, selectedSelector); const replica = deep(table); const list = fromTable$1(replica); const tableSize = TableSize.getTableSize(table); const replicaHouse = Warehouse.generate(list); const replicaStats = findSelectedStats(replicaHouse, isSelected); const selector = 'th:not(' + selectedSelector + ')' + ',td:not(' + selectedSelector + ')'; const unselectedCells = filterFirstLayer(replica, 'th,td', cell => is$2(cell, selector)); each$2(unselectedCells, remove$6); fillInGaps(list, replicaHouse, replicaStats, isSelected); const house = Warehouse.fromTable(table); const widthDelta = getTableWidthDelta(table, house, tableSize, replicaStats); clean(replica, replicaStats, replicaHouse, widthDelta); return replica; }; const nbsp = '\xA0'; const NodeValue = (is, name) => { const get = element => { if (!is(element)) { throw new Error('Can only get ' + name + ' value of a ' + name + ' node'); } return getOption(element).getOr(''); }; const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none(); const set = (element, value) => { if (!is(element)) { throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node'); } element.dom.nodeValue = value; }; return { get, getOption, set }; }; const api = NodeValue(isText, 'text'); const get$6 = element => api.get(element); const getOption = element => api.getOption(element); const set = (element, value) => api.set(element, value); const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$2(element).length, v => v.length); const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome(); const isContentEditableFalse = elem => isHTMLElement(elem) && get$b(elem, 'contenteditable') === 'false'; const elementsWithCursorPosition = [ 'img', 'br' ]; const isCursorPosition = elem => { const hasCursorPosition = isTextNodeWithCursorPosition(elem); return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse(elem); }; const first = element => descendant$1(element, isCursorPosition); const last$1 = element => descendantRtl(element, isCursorPosition); const descendantRtl = (scope, predicate) => { const descend = element => { const children = children$2(element); for (let i = children.length - 1; i >= 0; i--) { const child = children[i]; if (predicate(child)) { return Optional.some(child); } const res = descend(child); if (res.isSome()) { return res; } } return Optional.none(); }; return descend(scope); }; const transferableAttributes = { scope: [ 'row', 'col' ] }; const createCell = doc => () => { const td = SugarElement.fromTag('td', doc.dom); append$1(td, SugarElement.fromTag('br', doc.dom)); return td; }; const createCol = doc => () => { return SugarElement.fromTag('col', doc.dom); }; const createColgroup = doc => () => { return SugarElement.fromTag('colgroup', doc.dom); }; const createRow$1 = doc => () => { return SugarElement.fromTag('tr', doc.dom); }; const replace$1 = (cell, tag, attrs) => { const replica = copy$2(cell, tag); each$1(attrs, (v, k) => { if (v === null) { remove$7(replica, k); } else { set$2(replica, k, v); } }); return replica; }; const pasteReplace = cell => { return cell; }; const cloneFormats = (oldCell, newCell, formats) => { const first$1 = first(oldCell); return first$1.map(firstText => { const formatSelector = formats.join(','); const parents = ancestors$3(firstText, formatSelector, element => { return eq$1(element, oldCell); }); return foldr(parents, (last, parent) => { const clonedFormat = shallow(parent); append$1(last, clonedFormat); return clonedFormat; }, newCell); }).getOr(newCell); }; const cloneAppropriateAttributes = (original, clone) => { each$1(transferableAttributes, (validAttributes, attributeName) => getOpt(original, attributeName).filter(attribute => contains$2(validAttributes, attribute)).each(attribute => set$2(clone, attributeName, attribute))); }; const cellOperations = (mutate, doc, formatsToClone) => { const cloneCss = (prev, clone) => { copy$1(prev.element, clone); remove$5(clone, 'height'); if (prev.colspan !== 1) { remove$5(clone, 'width'); } }; const newCell = prev => { const td = SugarElement.fromTag(name(prev.element), doc.dom); const formats = formatsToClone.getOr([ 'strong', 'em', 'b', 'i', 'span', 'font', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div' ]); const lastNode = formats.length > 0 ? cloneFormats(prev.element, td, formats) : td; append$1(lastNode, SugarElement.fromTag('br')); cloneCss(prev, td); cloneAppropriateAttributes(prev.element, td); mutate(prev.element, td); return td; }; const newCol = prev => { const col = SugarElement.fromTag(name(prev.element), doc.dom); cloneCss(prev, col); mutate(prev.element, col); return col; }; return { col: newCol, colgroup: createColgroup(doc), row: createRow$1(doc), cell: newCell, replace: replace$1, colGap: createCol(doc), gap: createCell(doc) }; }; const paste$1 = doc => { return { col: createCol(doc), colgroup: createColgroup(doc), row: createRow$1(doc), cell: createCell(doc), replace: pasteReplace, colGap: createCol(doc), gap: createCell(doc) }; }; const fromHtml = (html, scope) => { const doc = scope || document; const div = doc.createElement('div'); div.innerHTML = html; return children$2(SugarElement.fromDom(div)); }; const fromDom = nodes => map$1(nodes, SugarElement.fromDom); const option = name => editor => editor.options.get(name); const defaultWidth = '100%'; const getPixelForcedWidth = editor => { var _a; const dom = editor.dom; const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody(); return getInner(SugarElement.fromDom(parentBlock)) + 'px'; }; const determineDefaultTableStyles = (editor, defaultStyles) => { if (isTableResponsiveForced(editor) || !shouldStyleWithCss(editor)) { return defaultStyles; } else if (isTablePixelsForced(editor)) { return { ...defaultStyles, width: getPixelForcedWidth(editor) }; } else { return { ...defaultStyles, width: defaultWidth }; } }; const determineDefaultTableAttributes = (editor, defaultAttributes) => { if (isTableResponsiveForced(editor) || shouldStyleWithCss(editor)) { return defaultAttributes; } else if (isTablePixelsForced(editor)) { return { ...defaultAttributes, width: getPixelForcedWidth(editor) }; } else { return { ...defaultAttributes, width: defaultWidth }; } }; const register = editor => { const registerOption = editor.options.register; registerOption('table_clone_elements', { processor: 'string[]' }); registerOption('table_use_colgroups', { processor: 'boolean', default: true }); registerOption('table_header_type', { processor: value => { const valid = contains$2([ 'section', 'cells', 'sectionCells', 'auto' ], value); return valid ? { value, valid } : { valid: false, message: 'Must be one of: section, cells, sectionCells or auto.' }; }, default: 'section' }); registerOption('table_sizing_mode', { processor: 'string', default: 'auto' }); registerOption('table_default_attributes', { processor: 'object', default: { border: '1' } }); registerOption('table_default_styles', { processor: 'object', default: { 'border-collapse': 'collapse' } }); registerOption('table_column_resizing', { processor: value => { const valid = contains$2([ 'preservetable', 'resizetable' ], value); return valid ? { value, valid } : { valid: false, message: 'Must be preservetable, or resizetable.' }; }, default: 'preservetable' }); registerOption('table_resize_bars', { processor: 'boolean', default: true }); registerOption('table_style_by_css', { processor: 'boolean', default: true }); registerOption('table_merge_content_on_paste', { processor: 'boolean', default: true }); }; const getTableCloneElements = editor => { return Optional.from(editor.options.get('table_clone_elements')); }; const hasTableObjectResizing = editor => { const objectResizing = editor.options.get('object_resizing'); return contains$2(objectResizing.split(','), 'table'); }; const getTableHeaderType = option('table_header_type'); const getTableColumnResizingBehaviour = option('table_column_resizing'); const isPreserveTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'preservetable'; const isResizeTableColumnResizing = editor => getTableColumnResizingBehaviour(editor) === 'resizetable'; const getTableSizingMode = option('table_sizing_mode'); const isTablePercentagesForced = editor => getTableSizingMode(editor) === 'relative'; const isTablePixelsForced = editor => getTableSizingMode(editor) === 'fixed'; const isTableResponsiveForced = editor => getTableSizingMode(editor) === 'responsive'; const hasTableResizeBars = option('table_resize_bars'); const shouldStyleWithCss = option('table_style_by_css'); const shouldMergeContentOnPaste = option('table_merge_content_on_paste'); const getTableDefaultAttributes = editor => { const options = editor.options; const defaultAttributes = options.get('table_default_attributes'); return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultTableAttributes(editor, defaultAttributes); }; const getTableDefaultStyles = editor => { const options = editor.options; const defaultStyles = options.get('table_default_styles'); return options.isSet('table_default_styles') ? defaultStyles : determineDefaultTableStyles(editor, defaultStyles); }; const tableUseColumnGroup = option('table_use_colgroups'); const fixedContainerSelector = option('fixed_toolbar_container'); const fixedToolbarContainerTarget = option('fixed_toolbar_container_target'); const fixedContainerTarget = editor => { var _a; if (!editor.inline) { return Optional.none(); } const selector = (_a = fixedContainerSelector(editor)) !== null && _a !== void 0 ? _a : ''; if (selector.length > 0) { return descendant(body$1(), selector); } const element = fixedToolbarContainerTarget(editor); if (isNonNullable(element)) { return Optional.some(SugarElement.fromDom(element)); } return Optional.none(); }; const useFixedContainer = editor => editor.inline && fixedContainerTarget(editor).isSome(); const getUiMode = option('ui_mode'); const isSplitUiMode = editor => !useFixedContainer(editor) && getUiMode(editor) === 'split'; const closest = target => closest$1(target, '[contenteditable]'); const isEditable$1 = (element, assumeEditable = false) => { if (inBody(element)) { return element.dom.isContentEditable; } else { return closest(element).fold(constant(assumeEditable), editable => getRaw(editable) === 'true'); } }; const getRaw = element => element.dom.contentEditable; const getBody = editor => SugarElement.fromDom(editor.getBody()); const getIsRoot = editor => element => eq$1(element, getBody(editor)); const removeDataStyle = table => { remove$7(table, 'data-mce-style'); const removeStyleAttribute = element => remove$7(element, 'data-mce-style'); each$2(cells$1(table), removeStyleAttribute); each$2(columns$1(table), removeStyleAttribute); each$2(rows$1(table), removeStyleAttribute); }; const getSelectionStart = editor => SugarElement.fromDom(editor.selection.getStart()); const getPixelWidth = elm => elm.getBoundingClientRect().width; const getPixelHeight = elm => elm.getBoundingClientRect().height; const getRawValue = prop => (editor, elm) => { const raw = editor.dom.getStyle(elm, prop) || editor.dom.getAttrib(elm, prop); return Optional.from(raw).filter(isNotEmpty); }; const getRawWidth = getRawValue('width'); const getRawHeight = getRawValue('height'); const isPercentage$1 = value => /^(\d+(\.\d+)?)%$/.test(value); const isPixel = value => /^(\d+(\.\d+)?)px$/.test(value); const isInEditableContext$1 = cell => closest$2(cell, isTag('table')).exists(isEditable$1); const inSelection = (bounds, detail) => { const leftEdge = detail.column; const rightEdge = detail.column + detail.colspan - 1; const topEdge = detail.row; const bottomEdge = detail.row + detail.rowspan - 1; return leftEdge <= bounds.finishCol && rightEdge >= bounds.startCol && (topEdge <= bounds.finishRow && bottomEdge >= bounds.startRow); }; const isWithin = (bounds, detail) => { return detail.column >= bounds.startCol && detail.column + detail.colspan - 1 <= bounds.finishCol && detail.row >= bounds.startRow && detail.row + detail.rowspan - 1 <= bounds.finishRow; }; const isRectangular = (warehouse, bounds) => { let isRect = true; const detailIsWithin = curry(isWithin, bounds); for (let i = bounds.startRow; i <= bounds.finishRow; i++) { for (let j = bounds.startCol; j <= bounds.finishCol; j++) { isRect = isRect && Warehouse.getAt(warehouse, i, j).exists(detailIsWithin); } } return isRect ? Optional.some(bounds) : Optional.none(); }; const getBounds = (detailA, detailB) => { return bounds(Math.min(detailA.row, detailB.row), Math.min(detailA.column, detailB.column), Math.max(detailA.row + detailA.rowspan - 1, detailB.row + detailB.rowspan - 1), Math.max(detailA.column + detailA.colspan - 1, detailB.column + detailB.colspan - 1)); }; const getAnyBox = (warehouse, startCell, finishCell) => { const startCoords = Warehouse.findItem(warehouse, startCell, eq$1); const finishCoords = Warehouse.findItem(warehouse, finishCell, eq$1); return startCoords.bind(sc => { return finishCoords.map(fc => { return getBounds(sc, fc); }); }); }; const getBox$1 = (warehouse, startCell, finishCell) => { return getAnyBox(warehouse, startCell, finishCell).bind(bounds => { return isRectangular(warehouse, bounds); }); }; const moveBy$1 = (warehouse, cell, row, column) => { return Warehouse.findItem(warehouse, cell, eq$1).bind(detail => { const startRow = row > 0 ? detail.row + detail.rowspan - 1 : detail.row; const startCol = column > 0 ? detail.column + detail.colspan - 1 : detail.column; const dest = Warehouse.getAt(warehouse, startRow + row, startCol + column); return dest.map(d => { return d.element; }); }); }; const intercepts$1 = (warehouse, start, finish) => { return getAnyBox(warehouse, start, finish).map(bounds => { const inside = Warehouse.filterItems(warehouse, curry(inSelection, bounds)); return map$1(inside, detail => { return detail.element; }); }); }; const parentCell = (warehouse, innerCell) => { const isContainedBy = (c1, c2) => { return contains$1(c2, c1); }; return Warehouse.findItem(warehouse, innerCell, isContainedBy).map(detail => { return detail.element; }); }; const moveBy = (cell, deltaRow, deltaColumn) => { return table(cell).bind(table => { const warehouse = getWarehouse(table); return moveBy$1(warehouse, cell, deltaRow, deltaColumn); }); }; const intercepts = (table, first, last) => { const warehouse = getWarehouse(table); return intercepts$1(warehouse, first, last); }; const nestedIntercepts = (table, first, firstTable, last, lastTable) => { const warehouse = getWarehouse(table); const optStartCell = eq$1(table, firstTable) ? Optional.some(first) : parentCell(warehouse, first); const optLastCell = eq$1(table, lastTable) ? Optional.some(last) : parentCell(warehouse, last); return optStartCell.bind(startCell => optLastCell.bind(lastCell => intercepts$1(warehouse, startCell, lastCell))); }; const getBox = (table, first, last) => { const warehouse = getWarehouse(table); return getBox$1(warehouse, first, last); }; const getWarehouse = Warehouse.fromTable; var TagBoundaries = [ 'body', 'p', 'div', 'article', 'aside', 'figcaption', 'figure', 'footer', 'header', 'nav', 'section', 'ol', 'ul', 'li', 'table', 'thead', 'tbody', 'tfoot', 'caption', 'tr', 'td', 'th', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre', 'address' ]; var DomUniverse = () => { const clone = element => { return SugarElement.fromDom(element.dom.cloneNode(false)); }; const document = element => documentOrOwner(element).dom; const isBoundary = element => { if (!isElement(element)) { return false; } if (name(element) === 'body') { return true; } return contains$2(TagBoundaries, name(element)); }; const isEmptyTag = element => { if (!isElement(element)) { return false; } return contains$2([ 'br', 'img', 'hr', 'input' ], name(element)); }; const isNonEditable = element => isElement(element) && get$b(element, 'contenteditable') === 'false'; const comparePosition = (element, other) => { return element.dom.compareDocumentPosition(other.dom); }; const copyAttributesTo = (source, destination) => { const as = clone$2(source); setAll$1(destination, as); }; const isSpecial = element => { const tag = name(element); return contains$2([ 'script', 'noscript', 'iframe', 'noframes', 'noembed', 'title', 'style', 'textarea', 'xmp' ], tag); }; const getLanguage = element => isElement(element) ? getOpt(element, 'lang') : Optional.none(); return { up: constant({ selector: ancestor$1, closest: closest$1, predicate: ancestor$2, all: parents }), down: constant({ selector: descendants, predicate: descendants$1 }), styles: constant({ get: get$a, getRaw: getRaw$2, set: set$1, remove: remove$5 }), attrs: constant({ get: get$b, set: set$2, remove: remove$7, copyTo: copyAttributesTo }), insert: constant({ before: before$3, after: after$5, afterAll: after$4, append: append$1, appendAll: append, prepend: prepend, wrap: wrap }), remove: constant({ unwrap: unwrap, remove: remove$6 }), create: constant({ nu: SugarElement.fromTag, clone, text: SugarElement.fromText }), query: constant({ comparePosition, prevSibling: prevSibling, nextSibling: nextSibling }), property: constant({ children: children$2, name: name, parent: parent, document, isText: isText, isComment: isComment, isElement: isElement, isSpecial, getLanguage, getText: get$6, setText: set, isBoundary, isEmptyTag, isNonEditable }), eq: eq$1, is: is$1 }; }; const all = (universe, look, elements, f) => { const head = elements[0]; const tail = elements.slice(1); return f(universe, look, head, tail); }; const oneAll = (universe, look, elements) => { return elements.length > 0 ? all(universe, look, elements, unsafeOne) : Optional.none(); }; const unsafeOne = (universe, look, head, tail) => { const start = look(universe, head); return foldr(tail, (b, a) => { const current = look(universe, a); return commonElement(universe, b, current); }, start); }; const commonElement = (universe, start, end) => { return start.bind(s => { return end.filter(curry(universe.eq, s)); }); }; const eq = (universe, item) => { return curry(universe.eq, item); }; const ancestors$2 = (universe, start, end, isRoot = never) => { const ps1 = [start].concat(universe.up().all(start)); const ps2 = [end].concat(universe.up().all(end)); const prune = path => { const index = findIndex(path, isRoot); return index.fold(() => { return path; }, ind => { return path.slice(0, ind + 1); }); }; const pruned1 = prune(ps1); const pruned2 = prune(ps2); const shared = find$1(pruned1, x => { return exists(pruned2, eq(universe, x)); }); return { firstpath: pruned1, secondpath: pruned2, shared }; }; const sharedOne$1 = oneAll; const ancestors$1 = ancestors$2; const universe$3 = DomUniverse(); const sharedOne = (look, elements) => { return sharedOne$1(universe$3, (_universe, element) => { return look(element); }, elements); }; const ancestors = (start, finish, isRoot) => { return ancestors$1(universe$3, start, finish, isRoot); }; const lookupTable = container => { return ancestor$1(container, 'table'); }; const identify = (start, finish, isRoot) => { const getIsRoot = rootTable => { return element => { return isRoot !== undefined && isRoot(element) || eq$1(element, rootTable); }; }; if (eq$1(start, finish)) { return Optional.some({ boxes: Optional.some([start]), start, finish }); } else { return lookupTable(start).bind(startTable => { return lookupTable(finish).bind(finishTable => { if (eq$1(startTable, finishTable)) { return Optional.some({ boxes: intercepts(startTable, start, finish), start, finish }); } else if (contains$1(startTable, finishTable)) { const ancestorCells = ancestors$3(finish, 'td,th', getIsRoot(startTable)); const finishCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : finish; return Optional.some({ boxes: nestedIntercepts(startTable, start, startTable, finish, finishTable), start, finish: finishCell }); } else if (contains$1(finishTable, startTable)) { const ancestorCells = ancestors$3(start, 'td,th', getIsRoot(finishTable)); const startCell = ancestorCells.length > 0 ? ancestorCells[ancestorCells.length - 1] : start; return Optional.some({ boxes: nestedIntercepts(finishTable, start, startTable, finish, finishTable), start, finish: startCell }); } else { return ancestors(start, finish).shared.bind(lca => { return closest$1(lca, 'table', isRoot).bind(lcaTable => { const finishAncestorCells = ancestors$3(finish, 'td,th', getIsRoot(lcaTable)); const finishCell = finishAncestorCells.length > 0 ? finishAncestorCells[finishAncestorCells.length - 1] : finish; const startAncestorCells = ancestors$3(start, 'td,th', getIsRoot(lcaTable)); const startCell = startAncestorCells.length > 0 ? startAncestorCells[startAncestorCells.length - 1] : start; return Optional.some({ boxes: nestedIntercepts(lcaTable, start, startTable, finish, finishTable), start: startCell, finish: finishCell }); }); }); } }); }); } }; const retrieve$1 = (container, selector) => { const sels = descendants(container, selector); return sels.length > 0 ? Optional.some(sels) : Optional.none(); }; const getLast = (boxes, lastSelectedSelector) => { return find$1(boxes, box => { return is$2(box, lastSelectedSelector); }); }; const getEdges = (container, firstSelectedSelector, lastSelectedSelector) => { return descendant(container, firstSelectedSelector).bind(first => { return descendant(container, lastSelectedSelector).bind(last => { return sharedOne(lookupTable, [ first, last ]).map(table => { return { first, last, table }; }); }); }); }; const expandTo = (finish, firstSelectedSelector) => { return ancestor$1(finish, 'table').bind(table => { return descendant(table, firstSelectedSelector).bind(start => { return identify(start, finish).bind(identified => { return identified.boxes.map(boxes => { return { boxes, start: identified.start, finish: identified.finish }; }); }); }); }); }; const shiftSelection = (boxes, deltaRow, deltaColumn, firstSelectedSelector, lastSelectedSelector) => { return getLast(boxes, lastSelectedSelector).bind(last => { return moveBy(last, deltaRow, deltaColumn).bind(finish => { return expandTo(finish, firstSelectedSelector); }); }); }; const retrieve = (container, selector) => { return retrieve$1(container, selector); }; const retrieveBox = (container, firstSelectedSelector, lastSelectedSelector) => { return getEdges(container, firstSelectedSelector, lastSelectedSelector).bind(edges => { const isRoot = ancestor => { return eq$1(container, ancestor); }; const sectionSelector = 'thead,tfoot,tbody,table'; const firstAncestor = ancestor$1(edges.first, sectionSelector, isRoot); const lastAncestor = ancestor$1(edges.last, sectionSelector, isRoot); return firstAncestor.bind(fA => { return lastAncestor.bind(lA => { return eq$1(fA, lA) ? getBox(edges.table, edges.first, edges.last) : Optional.none(); }); }); }); }; const selection = identity; const unmergable = selectedCells => { const hasSpan = (elem, type) => getOpt(elem, type).exists(span => parseInt(span, 10) > 1); const hasRowOrColSpan = elem => hasSpan(elem, 'rowspan') || hasSpan(elem, 'colspan'); return selectedCells.length > 0 && forall(selectedCells, hasRowOrColSpan) ? Optional.some(selectedCells) : Optional.none(); }; const mergable = (table, selectedCells, ephemera) => { if (selectedCells.length <= 1) { return Optional.none(); } else { return retrieveBox(table, ephemera.firstSelectedSelector, ephemera.lastSelectedSelector).map(bounds => ({ bounds, cells: selectedCells })); } }; const strSelected = 'data-mce-selected'; const strSelectedSelector = 'td[' + strSelected + '],th[' + strSelected + ']'; const strAttributeSelector = '[' + strSelected + ']'; const strFirstSelected = 'data-mce-first-selected'; const strFirstSelectedSelector = 'td[' + strFirstSelected + '],th[' + strFirstSelected + ']'; const strLastSelected = 'data-mce-last-selected'; const strLastSelectedSelector = 'td[' + strLastSelected + '],th[' + strLastSelected + ']'; const attributeSelector = strAttributeSelector; const ephemera = { selected: strSelected, selectedSelector: strSelectedSelector, firstSelected: strFirstSelected, firstSelectedSelector: strFirstSelectedSelector, lastSelected: strLastSelected, lastSelectedSelector: strLastSelectedSelector }; const forMenu = (selectedCells, table, cell) => ({ element: cell, mergable: mergable(table, selectedCells, ephemera), unmergable: unmergable(selectedCells), selection: selection(selectedCells) }); const paste = (element, clipboard, generators) => ({ element, clipboard, generators }); const pasteRows = (selectedCells, _cell, clipboard, generators) => ({ selection: selection(selectedCells), clipboard, generators }); const getSelectionCellFallback = element => table(element).bind(table => retrieve(table, ephemera.firstSelectedSelector)).fold(constant(element), cells => cells[0]); const getSelectionFromSelector = selector => (initCell, isRoot) => { const cellName = name(initCell); const cell = cellName === 'col' || cellName === 'colgroup' ? getSelectionCellFallback(initCell) : initCell; return closest$1(cell, selector, isRoot); }; const getSelectionCellOrCaption = getSelectionFromSelector('th,td,caption'); const getSelectionCell = getSelectionFromSelector('th,td'); const getCellsFromSelection = editor => fromDom(editor.model.table.getSelectedCells()); const getCellsFromFakeSelection = editor => filter$2(getCellsFromSelection(editor), cell => is$2(cell, ephemera.selectedSelector)); const extractSelected = cells => { return table(cells[0]).map(table => { const replica = extract$1(table, attributeSelector); removeDataStyle(replica); return [replica]; }); }; const serializeElements = (editor, elements) => map$1(elements, elm => editor.selection.serializer.serialize(elm.dom, {})).join(''); const getTextContent = (editor, replicaElements) => { const doc = editor.getDoc(); const dos = getRootNode(SugarElement.fromDom(editor.getBody())); const offscreenDiv = SugarElement.fromTag('div', doc); set$2(offscreenDiv, 'data-mce-bogus', 'all'); setAll(offscreenDiv, { position: 'fixed', left: '-9999999px', top: '0', overflow: 'hidden', opacity: '0' }); const root = getContentContainer(dos); append(offscreenDiv, replicaElements); append$1(root, offscreenDiv); const textContent = offscreenDiv.dom.innerText; remove$6(offscreenDiv); return textContent; }; const registerEvents = (editor, actions) => { editor.on('BeforeGetContent', e => { const multiCellContext = cells => { e.preventDefault(); extractSelected(cells).each(replicaElements => { const content = e.format === 'text' ? getTextContent(editor, replicaElements) : serializeElements(editor, replicaElements); e.content = content; }); }; if (e.selection === true) { const cells = getCellsFromFakeSelection(editor); if (cells.length >= 1) { multiCellContext(cells); } } }); editor.on('BeforeSetContent', e => { if (e.selection === true && e.paste === true) { const selectedCells = getCellsFromSelection(editor); head(selectedCells).each(cell => { table(cell).each(table => { const elements = filter$2(fromHtml(e.content), content => { return name(content) !== 'meta'; }); const isTable = isTag('table'); if (shouldMergeContentOnPaste(editor) && elements.length === 1 && isTable(elements[0])) { e.preventDefault(); const doc = SugarElement.fromDom(editor.getDoc()); const generators = paste$1(doc); const targets = paste(cell, elements[0], generators); actions.pasteCells(table, targets).each(() => { editor.focus(); }); } }); }); } }); }; const point = (element, offset) => ({ element, offset }); const scan$1 = (universe, element, direction) => { if (universe.property().isText(element) && universe.property().getText(element).trim().length === 0 || universe.property().isComment(element)) { return direction(element).bind(elem => { return scan$1(universe, elem, direction).orThunk(() => { return Optional.some(elem); }); }); } else { return Optional.none(); } }; const toEnd = (universe, element) => { if (universe.property().isText(element)) { return universe.property().getText(element).length; } const children = universe.property().children(element); return children.length; }; const freefallRtl$2 = (universe, element) => { const candidate = scan$1(universe, element, universe.query().prevSibling).getOr(element); if (universe.property().isText(candidate)) { return point(candidate, toEnd(universe, candidate)); } const children = universe.property().children(candidate); return children.length > 0 ? freefallRtl$2(universe, children[children.length - 1]) : point(candidate, toEnd(universe, candidate)); }; const freefallRtl$1 = freefallRtl$2; const universe$2 = DomUniverse(); const freefallRtl = element => { return freefallRtl$1(universe$2, element); }; const halve = (main, other) => { if (!hasColspan(main)) { const width = getGenericWidth(main); width.each(w => { const newWidth = w.value / 2; setGenericWidth(main, newWidth, w.unit); setGenericWidth(other, newWidth, w.unit); }); } }; const zero = array => map$1(array, constant(0)); const surround = (sizes, startIndex, endIndex, results, f) => f(sizes.slice(0, startIndex)).concat(results).concat(f(sizes.slice(endIndex))); const clampDeltaHelper = predicate => (sizes, index, delta, minCellSize) => { if (!predicate(delta)) { return delta; } else { const newSize = Math.max(minCellSize, sizes[index] - Math.abs(delta)); const diff = Math.abs(newSize - sizes[index]); return delta >= 0 ? diff : -diff; } }; const clampNegativeDelta = clampDeltaHelper(delta => delta < 0); const clampDelta = clampDeltaHelper(always); const resizeTable = () => { const calcFixedDeltas = (sizes, index, next, delta, minCellSize) => { const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize); return surround(sizes, index, next + 1, [ clampedDelta, 0 ], zero); }; const calcRelativeDeltas = (sizes, index, delta, minCellSize) => { const ratio = (100 + delta) / 100; const newThis = Math.max(minCellSize, (sizes[index] + delta) / ratio); return map$1(sizes, (size, idx) => { const newSize = idx === index ? newThis : size / ratio; return newSize - size; }); }; const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize, isRelative) => { if (isRelative) { return calcRelativeDeltas(sizes, index, delta, minCellSize); } else { return calcFixedDeltas(sizes, index, next, delta, minCellSize); } }; const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize, isRelative) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize, isRelative); const resizeTable = (resizer, delta) => resizer(delta); const calcRightEdgeDeltas = (sizes, _prev, index, delta, minCellSize, isRelative) => { if (isRelative) { return calcRelativeDeltas(sizes, index, delta, minCellSize); } else { const clampedDelta = clampNegativeDelta(sizes, index, delta, minCellSize); return zero(sizes.slice(0, index)).concat([clampedDelta]); } }; const calcRedestributedWidths = (sizes, totalWidth, pixelDelta, isRelative) => { if (isRelative) { const tableWidth = totalWidth + pixelDelta; const ratio = tableWidth / totalWidth; const newSizes = map$1(sizes, size => size / ratio); return { delta: ratio * 100 - 100, newSizes }; } else { return { delta: pixelDelta, newSizes: sizes }; } }; return { resizeTable, clampTableDelta: clampNegativeDelta, calcLeftEdgeDeltas, calcMiddleDeltas, calcRightEdgeDeltas, calcRedestributedWidths }; }; const preserveTable = () => { const calcLeftEdgeDeltas = (sizes, index, next, delta, minCellSize) => { const idx = delta >= 0 ? next : index; const clampedDelta = clampDelta(sizes, idx, delta, minCellSize); return surround(sizes, index, next + 1, [ clampedDelta, -clampedDelta ], zero); }; const calcMiddleDeltas = (sizes, _prev, index, next, delta, minCellSize) => calcLeftEdgeDeltas(sizes, index, next, delta, minCellSize); const resizeTable = (resizer, delta, isLastColumn) => { if (isLastColumn) { resizer(delta); } }; const calcRightEdgeDeltas = (sizes, _prev, _index, delta, _minCellSize, isRelative) => { if (isRelative) { return zero(sizes); } else { const diff = delta / sizes.length; return map$1(sizes, constant(diff)); } }; const clampTableDelta = (sizes, index, delta, minCellSize, isLastColumn) => { if (isLastColumn) { if (delta >= 0) { return delta; } else { const maxDelta = foldl(sizes, (a, b) => a + b - minCellSize, 0); return Math.max(-maxDelta, delta); } } else { return clampNegativeDelta(sizes, index, delta, minCellSize); } }; const calcRedestributedWidths = (sizes, _totalWidth, _pixelDelta, _isRelative) => ({ delta: 0, newSizes: sizes }); return { resizeTable, clampTableDelta, calcLeftEdgeDeltas, calcMiddleDeltas, calcRightEdgeDeltas, calcRedestributedWidths }; }; const getGridSize = table => { const warehouse = Warehouse.fromTable(table); return warehouse.grid; }; const isHeaderCell = isTag('th'); const isHeaderCells = cells => forall(cells, cell => isHeaderCell(cell.element)); const getRowHeaderType = (isHeaderRow, isHeaderCells) => { if (isHeaderRow && isHeaderCells) { return 'sectionCells'; } else if (isHeaderRow) { return 'section'; } else { return 'cells'; } }; const getRowType = row => { const isHeaderRow = row.section === 'thead'; const isHeaderCells = is(findCommonCellType(row.cells), 'th'); if (row.section === 'tfoot') { return { type: 'footer' }; } else if (isHeaderRow || isHeaderCells) { return { type: 'header', subType: getRowHeaderType(isHeaderRow, isHeaderCells) }; } else { return { type: 'body' }; } }; const findCommonCellType = cells => { const headerCells = filter$2(cells, cell => isHeaderCell(cell.element)); if (headerCells.length === 0) { return Optional.some('td'); } else if (headerCells.length === cells.length) { return Optional.some('th'); } else { return Optional.none(); } }; const findCommonRowType = rows => { const rowTypes = map$1(rows, row => getRowType(row).type); const hasHeader = contains$2(rowTypes, 'header'); const hasFooter = contains$2(rowTypes, 'footer'); if (!hasHeader && !hasFooter) { return Optional.some('body'); } else { const hasBody = contains$2(rowTypes, 'body'); if (hasHeader && !hasBody && !hasFooter) { return Optional.some('header'); } else if (!hasHeader && !hasBody && hasFooter) { return Optional.some('footer'); } else { return Optional.none(); } } }; const findTableRowHeaderType = warehouse => findMap(warehouse.all, row => { const rowType = getRowType(row); return rowType.type === 'header' ? Optional.from(rowType.subType) : Optional.none(); }); const transformCell = (cell, comparator, substitution) => elementnew(substitution(cell.element, comparator), true, cell.isLocked); const transformRow = (row, section) => row.section !== section ? rowcells(row.element, row.cells, section, row.isNew) : row; const section = () => ({ transformRow, transformCell: (cell, comparator, substitution) => { const newCell = substitution(cell.element, comparator); const fixedCell = name(newCell) !== 'td' ? mutate$1(newCell, 'td') : newCell; return elementnew(fixedCell, cell.isNew, cell.isLocked); } }); const sectionCells = () => ({ transformRow, transformCell }); const cells = () => ({ transformRow: (row, section) => { const newSection = section === 'thead' ? 'tbody' : section; return transformRow(row, newSection); }, transformCell }); const fallback = () => ({ transformRow: identity, transformCell }); const getTableSectionType = (table, fallback) => { const warehouse = Warehouse.fromTable(table); const type = findTableRowHeaderType(warehouse).getOr(fallback); switch (type) { case 'section': return section(); case 'sectionCells': return sectionCells(); case 'cells': return cells(); } }; const TableSection = { getTableSectionType, section, sectionCells, cells, fallback }; const setIfNot = (element, property, value, ignore) => { if (value === ignore) { remove$7(element, property); } else { set$2(element, property, value); } }; const insert$1 = (table, selector, element) => { last$2(children(table, selector)).fold(() => prepend(table, element), child => after$5(child, element)); }; const generateSection = (table, sectionName) => { const section = child(table, sectionName).getOrThunk(() => { const newSection = SugarElement.fromTag(sectionName, owner(table).dom); if (sectionName === 'thead') { insert$1(table, 'caption,colgroup', newSection); } else if (sectionName === 'colgroup') { insert$1(table, 'caption', newSection); } else { append$1(table, newSection); } return newSection; }); empty(section); return section; }; const render$1 = (table, grid) => { const newRows = []; const newCells = []; const syncRows = gridSection => map$1(gridSection, row => { if (row.isNew) { newRows.push(row.element); } const tr = row.element; empty(tr); each$2(row.cells, cell => { if (cell.isNew) { newCells.push(cell.element); } setIfNot(cell.element, 'colspan', cell.colspan, 1); setIfNot(cell.element, 'rowspan', cell.rowspan, 1); append$1(tr, cell.element); }); return tr; }); const syncColGroup = gridSection => bind$2(gridSection, colGroup => map$1(colGroup.cells, col => { setIfNot(col.element, 'span', col.colspan, 1); return col.element; })); const renderSection = (gridSection, sectionName) => { const section = generateSection(table, sectionName); const sync = sectionName === 'colgroup' ? syncColGroup : syncRows; const sectionElems = sync(gridSection); append(section, sectionElems); }; const removeSection = sectionName => { child(table, sectionName).each(remove$6); }; const renderOrRemoveSection = (gridSection, sectionName) => { if (gridSection.length > 0) { renderSection(gridSection, sectionName); } else { removeSection(sectionName); } }; const headSection = []; const bodySection = []; const footSection = []; const columnGroupsSection = []; each$2(grid, row => { switch (row.section) { case 'thead': headSection.push(row); break; case 'tbody': bodySection.push(row); break; case 'tfoot': footSection.push(row); break; case 'colgroup': columnGroupsSection.push(row); break; } }); renderOrRemoveSection(columnGroupsSection, 'colgroup'); renderOrRemoveSection(headSection, 'thead'); renderOrRemoveSection(bodySection, 'tbody'); renderOrRemoveSection(footSection, 'tfoot'); return { newRows, newCells }; }; const copy = grid => map$1(grid, row => { const tr = shallow(row.element); each$2(row.cells, cell => { const clonedCell = deep(cell.element); setIfNot(clonedCell, 'colspan', cell.colspan, 1); setIfNot(clonedCell, 'rowspan', cell.rowspan, 1); append$1(tr, clonedCell); }); return tr; }); const getColumn = (grid, index) => { return map$1(grid, row => { return getCell(row, index); }); }; const getRow = (grid, index) => { return grid[index]; }; const findDiff = (xs, comp) => { if (xs.length === 0) { return 0; } const first = xs[0]; const index = findIndex(xs, x => { return !comp(first.element, x.element); }); return index.getOr(xs.length); }; const subgrid = (grid, row, column, comparator) => { const gridRow = getRow(grid, row); const isColRow = gridRow.section === 'colgroup'; const colspan = findDiff(gridRow.cells.slice(column), comparator); const rowspan = isColRow ? 1 : findDiff(getColumn(grid.slice(row), column), comparator); return { colspan, rowspan }; }; const toDetails = (grid, comparator) => { const seen = map$1(grid, row => map$1(row.cells, never)); const updateSeen = (rowIndex, columnIndex, rowspan, colspan) => { for (let row = rowIndex; row < rowIndex + rowspan; row++) { for (let column = columnIndex; column < columnIndex + colspan; column++) { seen[row][column] = true; } } }; return map$1(grid, (row, rowIndex) => { const details = bind$2(row.cells, (cell, columnIndex) => { if (seen[rowIndex][columnIndex] === false) { const result = subgrid(grid, rowIndex, columnIndex, comparator); updateSeen(rowIndex, columnIndex, result.rowspan, result.colspan); return [detailnew(cell.element, result.rowspan, result.colspan, cell.isNew)]; } else { return []; } }); return rowdetailnew(row.element, details, row.section, row.isNew); }); }; const toGrid = (warehouse, generators, isNew) => { const grid = []; each$2(warehouse.colgroups, colgroup => { const colgroupCols = []; for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) { const element = Warehouse.getColumnAt(warehouse, columnIndex).map(column => elementnew(column.element, isNew, false)).getOrThunk(() => elementnew(generators.colGap(), true, false)); colgroupCols.push(element); } grid.push(rowcells(colgroup.element, colgroupCols, 'colgroup', isNew)); }); for (let rowIndex = 0; rowIndex < warehouse.grid.rows; rowIndex++) { const rowCells = []; for (let columnIndex = 0; columnIndex < warehouse.grid.columns; columnIndex++) { const element = Warehouse.getAt(warehouse, rowIndex, columnIndex).map(item => elementnew(item.element, isNew, item.isLocked)).getOrThunk(() => elementnew(generators.gap(), true, false)); rowCells.push(element); } const rowDetail = warehouse.all[rowIndex]; const row = rowcells(rowDetail.element, rowCells, rowDetail.section, isNew); grid.push(row); } return grid; }; const fromWarehouse = (warehouse, generators) => toGrid(warehouse, generators, false); const toDetailList = grid => toDetails(grid, eq$1); const findInWarehouse = (warehouse, element) => findMap(warehouse.all, r => find$1(r.cells, e => eq$1(element, e.element))); const extractCells = (warehouse, target, predicate) => { const details = map$1(target.selection, cell$1 => { return cell(cell$1).bind(lc => findInWarehouse(warehouse, lc)).filter(predicate); }); const cells = cat(details); return someIf(cells.length > 0, cells); }; const run = (operation, extract, adjustment, postAction, genWrappers) => (table, target, generators, behaviours) => { const warehouse = Warehouse.fromTable(table); const tableSection = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.section).getOrThunk(TableSection.fallback); const output = extract(warehouse, target).map(info => { const model = fromWarehouse(warehouse, generators); const result = operation(model, info, eq$1, genWrappers(generators), tableSection); const lockedColumns = getLockedColumnsFromGrid(result.grid); const grid = toDetailList(result.grid); return { info, grid, cursor: result.cursor, lockedColumns }; }); return output.bind(out => { const newElements = render$1(table, out.grid); const tableSizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.sizing).getOrThunk(() => TableSize.getTableSize(table)); const resizing = Optional.from(behaviours === null || behaviours === void 0 ? void 0 : behaviours.resize).getOrThunk(preserveTable); adjustment(table, out.grid, out.info, { sizing: tableSizing, resize: resizing, section: tableSection }); postAction(table); remove$7(table, LOCKED_COL_ATTR); if (out.lockedColumns.length > 0) { set$2(table, LOCKED_COL_ATTR, out.lockedColumns.join(',')); } return Optional.some({ cursor: out.cursor, newRows: newElements.newRows, newCells: newElements.newCells }); }); }; const onPaste = (warehouse, target) => cell(target.element).bind(cell => findInWarehouse(warehouse, cell).map(details => { const value = { ...details, generators: target.generators, clipboard: target.clipboard }; return value; })); const onPasteByEditor = (warehouse, target) => extractCells(warehouse, target, always).map(cells => ({ cells, generators: target.generators, clipboard: target.clipboard })); const onMergable = (_warehouse, target) => target.mergable; const onUnmergable = (_warehouse, target) => target.unmergable; const onCells = (warehouse, target) => extractCells(warehouse, target, always); const onUnlockedCells = (warehouse, target) => extractCells(warehouse, target, detail => !detail.isLocked); const isUnlockedTableCell = (warehouse, cell) => findInWarehouse(warehouse, cell).exists(detail => !detail.isLocked); const allUnlocked = (warehouse, cells) => forall(cells, cell => isUnlockedTableCell(warehouse, cell)); const onUnlockedMergable = (warehouse, target) => onMergable(warehouse, target).filter(mergeable => allUnlocked(warehouse, mergeable.cells)); const onUnlockedUnmergable = (warehouse, target) => onUnmergable(warehouse, target).filter(cells => allUnlocked(warehouse, cells)); const merge$2 = (grid, bounds, comparator, substitution) => { const rows = extractGridDetails(grid).rows; if (rows.length === 0) { return grid; } for (let i = bounds.startRow; i <= bounds.finishRow; i++) { for (let j = bounds.startCol; j <= bounds.finishCol; j++) { const row = rows[i]; const isLocked = getCell(row, j).isLocked; mutateCell(row, j, elementnew(substitution(), false, isLocked)); } } return grid; }; const unmerge = (grid, target, comparator, substitution) => { const rows = extractGridDetails(grid).rows; let first = true; for (let i = 0; i < rows.length; i++) { for (let j = 0; j < cellLength(rows[0]); j++) { const row = rows[i]; const currentCell = getCell(row, j); const currentCellElm = currentCell.element; const isToReplace = comparator(currentCellElm, target); if (isToReplace && !first) { mutateCell(row, j, elementnew(substitution(), true, currentCell.isLocked)); } else if (isToReplace) { first = false; } } } return grid; }; const uniqueCells = (row, comparator) => { return foldl(row, (rest, cell) => { return exists(rest, currentCell => { return comparator(currentCell.element, cell.element); }) ? rest : rest.concat([cell]); }, []); }; const splitCols = (grid, index, comparator, substitution) => { if (index > 0 && index < grid[0].cells.length) { each$2(grid, row => { const prevCell = row.cells[index - 1]; let offset = 0; const substitute = substitution(); while (row.cells.length > index + offset && comparator(prevCell.element, row.cells[index + offset].element)) { mutateCell(row, index + offset, elementnew(substitute, true, row.cells[index + offset].isLocked)); offset++; } }); } return grid; }; const splitRows = (grid, index, comparator, substitution) => { const rows = extractGridDetails(grid).rows; if (index > 0 && index < rows.length) { const rowPrevCells = rows[index - 1].cells; const cells = uniqueCells(rowPrevCells, comparator); each$2(cells, cell => { let replacement = Optional.none(); for (let i = index; i < rows.length; i++) { for (let j = 0; j < cellLength(rows[0]); j++) { const row = rows[i]; const current = getCell(row, j); const isToReplace = comparator(current.element, cell.element); if (isToReplace) { if (replacement.isNone()) { replacement = Optional.some(substitution()); } replacement.each(sub => { mutateCell(row, j, elementnew(sub, true, current.isLocked)); }); } } } }); } return grid; }; const value$1 = value => { const applyHelper = fn => fn(value); const constHelper = constant(value); const outputHelper = () => output; const output = { tag: true, inner: value, fold: (_onError, onValue) => onValue(value), isValue: always, isError: never, map: mapper => Result.value(mapper(value)), mapError: outputHelper, bind: applyHelper, exists: applyHelper, forall: applyHelper, getOr: constHelper, or: outputHelper, getOrThunk: constHelper, orThunk: outputHelper, getOrDie: constHelper, each: fn => { fn(value); }, toOptional: () => Optional.some(value) }; return output; }; const error = error => { const outputHelper = () => output; const output = { tag: false, inner: error, fold: (onError, _onValue) => onError(error), isValue: never, isError: always, map: outputHelper, mapError: mapper => Result.error(mapper(error)), bind: outputHelper, exists: never, forall: always, getOr: identity, or: identity, getOrThunk: apply, orThunk: apply, getOrDie: die(String(error)), each: noop, toOptional: Optional.none }; return output; }; const fromOption = (optional, err) => optional.fold(() => error(err), value$1); const Result = { value: value$1, error, fromOption }; const measure = (startAddress, gridA, gridB) => { if (startAddress.row >= gridA.length || startAddress.column > cellLength(gridA[0])) { return Result.error('invalid start address out of table bounds, row: ' + startAddress.row + ', column: ' + startAddress.column); } const rowRemainder = gridA.slice(startAddress.row); const colRemainder = rowRemainder[0].cells.slice(startAddress.column); const colRequired = cellLength(gridB[0]); const rowRequired = gridB.length; return Result.value({ rowDelta: rowRemainder.length - rowRequired, colDelta: colRemainder.length - colRequired }); }; const measureWidth = (gridA, gridB) => { const colLengthA = cellLength(gridA[0]); const colLengthB = cellLength(gridB[0]); return { rowDelta: 0, colDelta: colLengthA - colLengthB }; }; const measureHeight = (gridA, gridB) => { const rowLengthA = gridA.length; const rowLengthB = gridB.length; return { rowDelta: rowLengthA - rowLengthB, colDelta: 0 }; }; const generateElements = (amount, row, generators, isLocked) => { const generator = row.section === 'colgroup' ? generators.col : generators.cell; return range$1(amount, idx => elementnew(generator(), true, isLocked(idx))); }; const rowFill = (grid, amount, generators, lockedColumns) => { const exampleRow = grid[grid.length - 1]; return grid.concat(range$1(amount, () => { const generator = exampleRow.section === 'colgroup' ? generators.colgroup : generators.row; const row = clone(exampleRow, generator, identity); const elements = generateElements(row.cells.length, row, generators, idx => has$1(lockedColumns, idx.toString())); return setCells(row, elements); })); }; const colFill = (grid, amount, generators, startIndex) => map$1(grid, row => { const newChildren = generateElements(amount, row, generators, never); return addCells(row, startIndex, newChildren); }); const lockedColFill = (grid, generators, lockedColumns) => map$1(grid, row => { return foldl(lockedColumns, (acc, colNum) => { const newChild = generateElements(1, row, generators, always)[0]; return addCell(acc, colNum, newChild); }, row); }); const tailor = (gridA, delta, generators) => { const fillCols = delta.colDelta < 0 ? colFill : identity; const fillRows = delta.rowDelta < 0 ? rowFill : identity; const lockedColumns = getLockedColumnsFromGrid(gridA); const gridWidth = cellLength(gridA[0]); const isLastColLocked = exists(lockedColumns, locked => locked === gridWidth - 1); const modifiedCols = fillCols(gridA, Math.abs(delta.colDelta), generators, isLastColLocked ? gridWidth - 1 : gridWidth); const newLockedColumns = getLockedColumnsFromGrid(modifiedCols); return fillRows(modifiedCols, Math.abs(delta.rowDelta), generators, mapToObject(newLockedColumns, always)); }; const isSpanning = (grid, row, col, comparator) => { const candidate = getCell(grid[row], col); const matching = curry(comparator, candidate.element); const currentRow = grid[row]; return grid.length > 1 && cellLength(currentRow) > 1 && (col > 0 && matching(getCellElement(currentRow, col - 1)) || col < currentRow.cells.length - 1 && matching(getCellElement(currentRow, col + 1)) || row > 0 && matching(getCellElement(grid[row - 1], col)) || row < grid.length - 1 && matching(getCellElement(grid[row + 1], col))); }; const mergeTables = (startAddress, gridA, gridBRows, generator, comparator, lockedColumns) => { const startRow = startAddress.row; const startCol = startAddress.column; const mergeHeight = gridBRows.length; const mergeWidth = cellLength(gridBRows[0]); const endRow = startRow + mergeHeight; const endCol = startCol + mergeWidth + lockedColumns.length; const lockedColumnObj = mapToObject(lockedColumns, always); for (let r = startRow; r < endRow; r++) { let skippedCol = 0; for (let c = startCol; c < endCol; c++) { if (lockedColumnObj[c]) { skippedCol++; continue; } if (isSpanning(gridA, r, c, comparator)) { unmerge(gridA, getCellElement(gridA[r], c), comparator, generator.cell); } const gridBColIndex = c - startCol - skippedCol; const newCell = getCell(gridBRows[r - startRow], gridBColIndex); const newCellElm = newCell.element; const replacement = generator.replace(newCellElm); mutateCell(gridA[r], c, elementnew(replacement, true, newCell.isLocked)); } } return gridA; }; const getValidStartAddress = (currentStartAddress, grid, lockedColumns) => { const gridColLength = cellLength(grid[0]); const adjustedRowAddress = extractGridDetails(grid).cols.length + currentStartAddress.row; const possibleColAddresses = range$1(gridColLength - currentStartAddress.column, num => num + currentStartAddress.column); const validColAddress = find$1(possibleColAddresses, num => forall(lockedColumns, col => col !== num)).getOr(gridColLength - 1); return { row: adjustedRowAddress, column: validColAddress }; }; const getLockedColumnsWithinBounds = (startAddress, rows, lockedColumns) => filter$2(lockedColumns, colNum => colNum >= startAddress.column && colNum <= cellLength(rows[0]) + startAddress.column); const merge$1 = (startAddress, gridA, gridB, generator, comparator) => { const lockedColumns = getLockedColumnsFromGrid(gridA); const validStartAddress = getValidStartAddress(startAddress, gridA, lockedColumns); const gridBRows = extractGridDetails(gridB).rows; const lockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, lockedColumns); const result = measure(validStartAddress, gridA, gridBRows); return result.map(diff => { const delta = { ...diff, colDelta: diff.colDelta - lockedColumnsWithinBounds.length }; const fittedGrid = tailor(gridA, delta, generator); const newLockedColumns = getLockedColumnsFromGrid(fittedGrid); const newLockedColumnsWithinBounds = getLockedColumnsWithinBounds(validStartAddress, gridBRows, newLockedColumns); return mergeTables(validStartAddress, fittedGrid, gridBRows, generator, comparator, newLockedColumnsWithinBounds); }); }; const insertCols = (index, gridA, gridB, generator, comparator) => { splitCols(gridA, index, comparator, generator.cell); const delta = measureHeight(gridB, gridA); const fittedNewGrid = tailor(gridB, delta, generator); const secondDelta = measureHeight(gridA, fittedNewGrid); const fittedOldGrid = tailor(gridA, secondDelta, generator); return map$1(fittedOldGrid, (gridRow, i) => { return addCells(gridRow, index, fittedNewGrid[i].cells); }); }; const insertRows = (index, gridA, gridB, generator, comparator) => { splitRows(gridA, index, comparator, generator.cell); const locked = getLockedColumnsFromGrid(gridA); const diff = measureWidth(gridA, gridB); const delta = { ...diff, colDelta: diff.colDelta - locked.length }; const fittedOldGrid = tailor(gridA, delta, generator); const { cols: oldCols, rows: oldRows } = extractGridDetails(fittedOldGrid); const newLocked = getLockedColumnsFromGrid(fittedOldGrid); const secondDiff = measureWidth(gridB, gridA); const secondDelta = { ...secondDiff, colDelta: secondDiff.colDelta + newLocked.length }; const fittedGridB = lockedColFill(gridB, generator, newLocked); const fittedNewGrid = tailor(fittedGridB, secondDelta, generator); return [ ...oldCols, ...oldRows.slice(0, index), ...fittedNewGrid, ...oldRows.slice(index, oldRows.length) ]; }; const cloneRow = (row, cloneCell, comparator, substitution) => clone(row, elem => substitution(elem, comparator), cloneCell); const insertRowAt = (grid, index, example, comparator, substitution) => { const {rows, cols} = extractGridDetails(grid); const before = rows.slice(0, index); const after = rows.slice(index); const newRow = cloneRow(rows[example], (ex, c) => { const withinSpan = index > 0 && index < rows.length && comparator(getCellElement(rows[index - 1], c), getCellElement(rows[index], c)); const ret = withinSpan ? getCell(rows[index], c) : elementnew(substitution(ex.element, comparator), true, ex.isLocked); return ret; }, comparator, substitution); return [ ...cols, ...before, newRow, ...after ]; }; const getElementFor = (row, column, section, withinSpan, example, comparator, substitution) => { if (section === 'colgroup' || !withinSpan) { const cell = getCell(row, example); return elementnew(substitution(cell.element, comparator), true, false); } else { return getCell(row, column); } }; const insertColumnAt = (grid, index, example, comparator, substitution) => map$1(grid, row => { const withinSpan = index > 0 && index < cellLength(row) && comparator(getCellElement(row, index - 1), getCellElement(row, index)); const sub = getElementFor(row, index, row.section, withinSpan, example, comparator, substitution); return addCell(row, index, sub); }); const deleteColumnsAt = (grid, columns) => bind$2(grid, row => { const existingCells = row.cells; const cells = foldr(columns, (acc, column) => column >= 0 && column < acc.length ? acc.slice(0, column).concat(acc.slice(column + 1)) : acc, existingCells); return cells.length > 0 ? [rowcells(row.element, cells, row.section, row.isNew)] : []; }); const deleteRowsAt = (grid, start, finish) => { const {rows, cols} = extractGridDetails(grid); return [ ...cols, ...rows.slice(0, start), ...rows.slice(finish + 1) ]; }; const notInStartRow = (grid, rowIndex, colIndex, comparator) => getCellElement(grid[rowIndex], colIndex) !== undefined && (rowIndex > 0 && comparator(getCellElement(grid[rowIndex - 1], colIndex), getCellElement(grid[rowIndex], colIndex))); const notInStartColumn = (row, index, comparator) => index > 0 && comparator(getCellElement(row, index - 1), getCellElement(row, index)); const isDuplicatedCell = (grid, rowIndex, colIndex, comparator) => notInStartRow(grid, rowIndex, colIndex, comparator) || notInStartColumn(grid[rowIndex], colIndex, comparator); const rowReplacerPredicate = (targetRow, columnHeaders) => { const entireTableIsHeader = forall(columnHeaders, identity) && isHeaderCells(targetRow.cells); return entireTableIsHeader ? always : (cell, _rowIndex, colIndex) => { const type = name(cell.element); return !(type === 'th' && columnHeaders[colIndex]); }; }; const columnReplacePredicate = (targetColumn, rowHeaders) => { const entireTableIsHeader = forall(rowHeaders, identity) && isHeaderCells(targetColumn); return entireTableIsHeader ? always : (cell, rowIndex, _colIndex) => { const type = name(cell.element); return !(type === 'th' && rowHeaders[rowIndex]); }; }; const determineScope = (applyScope, cell, newScope, isInHeader) => { const hasSpan = scope => scope === 'row' ? hasRowspan(cell) : hasColspan(cell); const getScope = scope => hasSpan(scope) ? `${ scope }group` : scope; if (applyScope) { return isHeaderCell(cell) ? getScope(newScope) : null; } else if (isInHeader && isHeaderCell(cell)) { const oppositeScope = newScope === 'row' ? 'col' : 'row'; return getScope(oppositeScope); } else { return null; } }; const rowScopeGenerator = (applyScope, columnHeaders) => (cell, rowIndex, columnIndex) => Optional.some(determineScope(applyScope, cell.element, 'col', columnHeaders[columnIndex])); const columnScopeGenerator = (applyScope, rowHeaders) => (cell, rowIndex) => Optional.some(determineScope(applyScope, cell.element, 'row', rowHeaders[rowIndex])); const replace = (cell, comparator, substitute) => elementnew(substitute(cell.element, comparator), true, cell.isLocked); const replaceIn = (grid, targets, comparator, substitute, replacer, genScope, shouldReplace) => { const isTarget = cell => { return exists(targets, target => { return comparator(cell.element, target.element); }); }; return map$1(grid, (row, rowIndex) => { return mapCells(row, (cell, colIndex) => { if (isTarget(cell)) { const newCell = shouldReplace(cell, rowIndex, colIndex) ? replacer(cell, comparator, substitute) : cell; genScope(newCell, rowIndex, colIndex).each(scope => { setOptions(newCell.element, { scope: Optional.from(scope) }); }); return newCell; } else { return cell; } }); }); }; const getColumnCells = (rows, columnIndex, comparator) => bind$2(rows, (row, i) => { return isDuplicatedCell(rows, i, columnIndex, comparator) ? [] : [getCell(row, columnIndex)]; }); const getRowCells = (rows, rowIndex, comparator) => { const targetRow = rows[rowIndex]; return bind$2(targetRow.cells, (item, i) => { return isDuplicatedCell(rows, rowIndex, i, comparator) ? [] : [item]; }); }; const replaceColumns = (grid, indexes, applyScope, comparator, substitution) => { const rows = extractGridDetails(grid).rows; const targets = bind$2(indexes, index => getColumnCells(rows, index, comparator)); const rowHeaders = map$1(rows, row => isHeaderCells(row.cells)); const shouldReplaceCell = columnReplacePredicate(targets, rowHeaders); const scopeGenerator = columnScopeGenerator(applyScope, rowHeaders); return replaceIn(grid, targets, comparator, substitution, replace, scopeGenerator, shouldReplaceCell); }; const replaceRows = (grid, indexes, section, applyScope, comparator, substitution, tableSection) => { const {cols, rows} = extractGridDetails(grid); const targetRow = rows[indexes[0]]; const targets = bind$2(indexes, index => getRowCells(rows, index, comparator)); const columnHeaders = map$1(targetRow.cells, (_cell, index) => isHeaderCells(getColumnCells(rows, index, comparator))); const newRows = [...rows]; each$2(indexes, index => { newRows[index] = tableSection.transformRow(rows[index], section); }); const newGrid = [ ...cols, ...newRows ]; const shouldReplaceCell = rowReplacerPredicate(targetRow, columnHeaders); const scopeGenerator = rowScopeGenerator(applyScope, columnHeaders); return replaceIn(newGrid, targets, comparator, substitution, tableSection.transformCell, scopeGenerator, shouldReplaceCell); }; const replaceCells = (grid, details, comparator, substitution) => { const rows = extractGridDetails(grid).rows; const targetCells = map$1(details, detail => getCell(rows[detail.row], detail.column)); return replaceIn(grid, targetCells, comparator, substitution, replace, Optional.none, always); }; const generate$1 = cases => { if (!isArray(cases)) { throw new Error('cases must be an array'); } if (cases.length === 0) { throw new Error('there must be at least one case'); } const constructors = []; const adt = {}; each$2(cases, (acase, count) => { const keys$1 = keys(acase); if (keys$1.length !== 1) { throw new Error('one and only one name per case'); } const key = keys$1[0]; const value = acase[key]; if (adt[key] !== undefined) { throw new Error('duplicate key detected:' + key); } else if (key === 'cata') { throw new Error('cannot have a case named cata (sorry)'); } else if (!isArray(value)) { throw new Error('case arguments must be an array'); } constructors.push(key); adt[key] = (...args) => { const argLength = args.length; if (argLength !== value.length) { throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength); } const match = branches => { const branchKeys = keys(branches); if (constructors.length !== branchKeys.length) { throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(',')); } const allReqd = forall(constructors, reqKey => { return contains$2(branchKeys, reqKey); }); if (!allReqd) { throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', ')); } return branches[key].apply(null, args); }; return { fold: (...foldArgs) => { if (foldArgs.length !== cases.length) { throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length); } const target = foldArgs[count]; return target.apply(null, args); }, match, log: label => { console.log(label, { constructors, constructor: key, params: args }); } }; }; }); return adt; }; const Adt = { generate: generate$1 }; const adt$6 = Adt.generate([ { none: [] }, { only: ['index'] }, { left: [ 'index', 'next' ] }, { middle: [ 'prev', 'index', 'next' ] }, { right: [ 'prev', 'index' ] } ]); const ColumnContext = { ...adt$6 }; const neighbours = (input, index) => { if (input.length === 0) { return ColumnContext.none(); } if (input.length === 1) { return ColumnContext.only(0); } if (index === 0) { return ColumnContext.left(0, 1); } if (index === input.length - 1) { return ColumnContext.right(index - 1, index); } if (index > 0 && index < input.length - 1) { return ColumnContext.middle(index - 1, index, index + 1); } return ColumnContext.none(); }; const determine = (input, column, step, tableSize, resize) => { const result = input.slice(0); const context = neighbours(input, column); const onNone = constant(map$1(result, constant(0))); const onOnly = index => tableSize.singleColumnWidth(result[index], step); const onLeft = (index, next) => resize.calcLeftEdgeDeltas(result, index, next, step, tableSize.minCellWidth(), tableSize.isRelative); const onMiddle = (prev, index, next) => resize.calcMiddleDeltas(result, prev, index, next, step, tableSize.minCellWidth(), tableSize.isRelative); const onRight = (prev, index) => resize.calcRightEdgeDeltas(result, prev, index, step, tableSize.minCellWidth(), tableSize.isRelative); return context.fold(onNone, onOnly, onLeft, onMiddle, onRight); }; const total = (start, end, measures) => { let r = 0; for (let i = start; i < end; i++) { r += measures[i] !== undefined ? measures[i] : 0; } return r; }; const recalculateWidthForCells = (warehouse, widths) => { const all = Warehouse.justCells(warehouse); return map$1(all, cell => { const width = total(cell.column, cell.column + cell.colspan, widths); return { element: cell.element, width, colspan: cell.colspan }; }); }; const recalculateWidthForColumns = (warehouse, widths) => { const groups = Warehouse.justColumns(warehouse); return map$1(groups, (column, index) => ({ element: column.element, width: widths[index], colspan: column.colspan })); }; const matchRowHeight = (warehouse, heights) => { return map$1(warehouse.all, (row, i) => { return { element: row.element, height: heights[i] }; }); }; const sumUp = newSize => foldr(newSize, (b, a) => b + a, 0); const recalculate = (warehouse, widths) => { if (Warehouse.hasColumns(warehouse)) { return recalculateWidthForColumns(warehouse, widths); } else { return recalculateWidthForCells(warehouse, widths); } }; const recalculateAndApply = (warehouse, widths, tableSize) => { const newSizes = recalculate(warehouse, widths); each$2(newSizes, cell => { tableSize.setElementWidth(cell.element, cell.width); }); }; const adjustWidth = (table, delta, index, resizing, tableSize) => { const warehouse = Warehouse.fromTable(table); const step = tableSize.getCellDelta(delta); const widths = tableSize.getWidths(warehouse, tableSize); const isLastColumn = index === warehouse.grid.columns - 1; const clampedStep = resizing.clampTableDelta(widths, index, step, tableSize.minCellWidth(), isLastColumn); const deltas = determine(widths, index, clampedStep, tableSize, resizing); const newWidths = map$1(deltas, (dx, i) => dx + widths[i]); recalculateAndApply(warehouse, newWidths, tableSize); resizing.resizeTable(tableSize.adjustTableWidth, clampedStep, isLastColumn); }; const adjustHeight = (table, delta, index) => { const warehouse = Warehouse.fromTable(table); const heights = getPixelHeights(warehouse, table); const newHeights = map$1(heights, (dy, i) => index === i ? Math.max(delta + dy, minHeight()) : dy); const newRowSizes = matchRowHeight(warehouse, newHeights); each$2(newRowSizes, row => { setHeight(row.element, row.height); }); each$2(Warehouse.justCells(warehouse), cell => { removeHeight(cell.element); }); const total = sumUp(newHeights); setHeight(table, total); }; const adjustAndRedistributeWidths$1 = (_table, list, details, tableSize, resizeBehaviour) => { const warehouse = Warehouse.generate(list); const sizes = tableSize.getWidths(warehouse, tableSize); const tablePixelWidth = tableSize.pixelWidth(); const {newSizes, delta} = resizeBehaviour.calcRedestributedWidths(sizes, tablePixelWidth, details.pixelDelta, tableSize.isRelative); recalculateAndApply(warehouse, newSizes, tableSize); tableSize.adjustTableWidth(delta); }; const adjustWidthTo = (_table, list, _info, tableSize) => { const warehouse = Warehouse.generate(list); const widths = tableSize.getWidths(warehouse, tableSize); recalculateAndApply(warehouse, widths, tableSize); }; const uniqueColumns = details => { const uniqueCheck = (rest, detail) => { const columnExists = exists(rest, currentDetail => currentDetail.column === detail.column); return columnExists ? rest : rest.concat([detail]); }; return foldl(details, uniqueCheck, []).sort((detailA, detailB) => detailA.column - detailB.column); }; const isCol = isTag('col'); const isColgroup = isTag('colgroup'); const isRow$1 = element => name(element) === 'tr' || isColgroup(element); const elementToData = element => { const colspan = getAttrValue(element, 'colspan', 1); const rowspan = getAttrValue(element, 'rowspan', 1); return { element, colspan, rowspan }; }; const modification = (generators, toData = elementToData) => { const nuCell = data => isCol(data.element) ? generators.col(data) : generators.cell(data); const nuRow = data => isColgroup(data.element) ? generators.colgroup(data) : generators.row(data); const add = element => { if (isRow$1(element)) { return nuRow({ element }); } else { const cell = element; const replacement = nuCell(toData(cell)); recent = Optional.some({ item: cell, replacement }); return replacement; } }; let recent = Optional.none(); const getOrInit = (element, comparator) => { return recent.fold(() => { return add(element); }, p => { return comparator(element, p.item) ? p.replacement : add(element); }); }; return { getOrInit }; }; const transform$1 = tag => { return generators => { const list = []; const find = (element, comparator) => { return find$1(list, x => { return comparator(x.item, element); }); }; const makeNew = element => { const attrs = tag === 'td' ? { scope: null } : {}; const cell = generators.replace(element, tag, attrs); list.push({ item: element, sub: cell }); return cell; }; const replaceOrInit = (element, comparator) => { if (isRow$1(element) || isCol(element)) { return element; } else { const cell = element; return find(cell, comparator).fold(() => { return makeNew(cell); }, p => { return comparator(element, p.item) ? p.sub : makeNew(cell); }); } }; return { replaceOrInit }; }; }; const getScopeAttribute = cell => getOpt(cell, 'scope').map(attribute => attribute.substr(0, 3)); const merging = generators => { const unmerge = cell => { const scope = getScopeAttribute(cell); scope.each(attribute => set$2(cell, 'scope', attribute)); return () => { const raw = generators.cell({ element: cell, colspan: 1, rowspan: 1 }); remove$5(raw, 'width'); remove$5(cell, 'width'); scope.each(attribute => set$2(raw, 'scope', attribute)); return raw; }; }; const merge = cells => { const getScopeProperty = () => { const stringAttributes = cat(map$1(cells, getScopeAttribute)); if (stringAttributes.length === 0) { return Optional.none(); } else { const baseScope = stringAttributes[0]; const scopes = [ 'row', 'col' ]; const isMixed = exists(stringAttributes, attribute => { return attribute !== baseScope && contains$2(scopes, attribute); }); return isMixed ? Optional.none() : Optional.from(baseScope); } }; remove$5(cells[0], 'width'); getScopeProperty().fold(() => remove$7(cells[0], 'scope'), attribute => set$2(cells[0], 'scope', attribute + 'group')); return constant(cells[0]); }; return { unmerge, merge }; }; const Generators = { modification, transform: transform$1, merging }; const blockList = [ 'body', 'p', 'div', 'article', 'aside', 'figcaption', 'figure', 'footer', 'header', 'nav', 'section', 'ol', 'ul', 'table', 'thead', 'tfoot', 'tbody', 'caption', 'tr', 'td', 'th', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre', 'address' ]; const isList$1 = (universe, item) => { const tagName = universe.property().name(item); return contains$2([ 'ol', 'ul' ], tagName); }; const isBlock$1 = (universe, item) => { const tagName = universe.property().name(item); return contains$2(blockList, tagName); }; const isEmptyTag$1 = (universe, item) => { return contains$2([ 'br', 'img', 'hr', 'input' ], universe.property().name(item)); }; const universe$1 = DomUniverse(); const isBlock = element => { return isBlock$1(universe$1, element); }; const isList = element => { return isList$1(universe$1, element); }; const isEmptyTag = element => { return isEmptyTag$1(universe$1, element); }; const merge = cells => { const isBr = isTag('br'); const advancedBr = children => { return forall(children, c => { return isBr(c) || isText(c) && get$6(c).trim().length === 0; }); }; const isListItem = el => { return name(el) === 'li' || ancestor$2(el, isList).isSome(); }; const siblingIsBlock = el => { return nextSibling(el).map(rightSibling => { if (isBlock(rightSibling)) { return true; } if (isEmptyTag(rightSibling)) { return name(rightSibling) === 'img' ? false : true; } return false; }).getOr(false); }; const markCell = cell => { return last$1(cell).bind(rightEdge => { const rightSiblingIsBlock = siblingIsBlock(rightEdge); return parent(rightEdge).map(parent => { return rightSiblingIsBlock === true || isListItem(parent) || isBr(rightEdge) || isBlock(parent) && !eq$1(cell, parent) ? [] : [SugarElement.fromTag('br')]; }); }).getOr([]); }; const markContent = () => { const content = bind$2(cells, cell => { const children = children$2(cell); return advancedBr(children) ? [] : children.concat(markCell(cell)); }); return content.length === 0 ? [SugarElement.fromTag('br')] : content; }; const contents = markContent(); empty(cells[0]); append(cells[0], contents); }; const isEditable = elem => isEditable$1(elem, true); const prune = table => { const cells = cells$1(table); if (cells.length === 0) { remove$6(table); } }; const outcome = (grid, cursor) => ({ grid, cursor }); const findEditableCursorPosition = rows => findMap(rows, row => findMap(row.cells, cell => { const elem = cell.element; return someIf(isEditable(elem), elem); })); const elementFromGrid = (grid, row, column) => { var _a, _b; const rows = extractGridDetails(grid).rows; return Optional.from((_b = (_a = rows[row]) === null || _a === void 0 ? void 0 : _a.cells[column]) === null || _b === void 0 ? void 0 : _b.element).filter(isEditable).orThunk(() => findEditableCursorPosition(rows)); }; const bundle = (grid, row, column) => { const cursorElement = elementFromGrid(grid, row, column); return outcome(grid, cursorElement); }; const uniqueRows = details => { const rowCompilation = (rest, detail) => { const rowExists = exists(rest, currentDetail => currentDetail.row === detail.row); return rowExists ? rest : rest.concat([detail]); }; return foldl(details, rowCompilation, []).sort((detailA, detailB) => detailA.row - detailB.row); }; const opInsertRowsBefore = (grid, details, comparator, genWrappers) => { const targetIndex = details[0].row; const rows = uniqueRows(details); const newGrid = foldr(rows, (acc, row) => { const newG = insertRowAt(acc.grid, targetIndex, row.row + acc.delta, comparator, genWrappers.getOrInit); return { grid: newG, delta: acc.delta + 1 }; }, { grid, delta: 0 }).grid; return bundle(newGrid, targetIndex, details[0].column); }; const opInsertRowsAfter = (grid, details, comparator, genWrappers) => { const rows = uniqueRows(details); const target = rows[rows.length - 1]; const targetIndex = target.row + target.rowspan; const newGrid = foldr(rows, (newG, row) => { return insertRowAt(newG, targetIndex, row.row, comparator, genWrappers.getOrInit); }, grid); return bundle(newGrid, targetIndex, details[0].column); }; const opInsertColumnsBefore = (grid, extractDetail, comparator, genWrappers) => { const details = extractDetail.details; const columns = uniqueColumns(details); const targetIndex = columns[0].column; const newGrid = foldr(columns, (acc, col) => { const newG = insertColumnAt(acc.grid, targetIndex, col.column + acc.delta, comparator, genWrappers.getOrInit); return { grid: newG, delta: acc.delta + 1 }; }, { grid, delta: 0 }).grid; return bundle(newGrid, details[0].row, targetIndex); }; const opInsertColumnsAfter = (grid, extractDetail, comparator, genWrappers) => { const details = extractDetail.details; const target = details[details.length - 1]; const targetIndex = target.column + target.colspan; const columns = uniqueColumns(details); const newGrid = foldr(columns, (newG, col) => { return insertColumnAt(newG, targetIndex, col.column, comparator, genWrappers.getOrInit); }, grid); return bundle(newGrid, details[0].row, targetIndex); }; const opMakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => { const columns = uniqueColumns(details); const columnIndexes = map$1(columns, detail => detail.column); const newGrid = replaceColumns(initialGrid, columnIndexes, true, comparator, genWrappers.replaceOrInit); return bundle(newGrid, details[0].row, details[0].column); }; const opMakeCellsHeader = (initialGrid, details, comparator, genWrappers) => { const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit); return bundle(newGrid, details[0].row, details[0].column); }; const opUnmakeColumnsHeader = (initialGrid, details, comparator, genWrappers) => { const columns = uniqueColumns(details); const columnIndexes = map$1(columns, detail => detail.column); const newGrid = replaceColumns(initialGrid, columnIndexes, false, comparator, genWrappers.replaceOrInit); return bundle(newGrid, details[0].row, details[0].column); }; const opUnmakeCellsHeader = (initialGrid, details, comparator, genWrappers) => { const newGrid = replaceCells(initialGrid, details, comparator, genWrappers.replaceOrInit); return bundle(newGrid, details[0].row, details[0].column); }; const makeRowsSection = (section, applyScope) => (initialGrid, details, comparator, genWrappers, tableSection) => { const rows = uniqueRows(details); const rowIndexes = map$1(rows, detail => detail.row); const newGrid = replaceRows(initialGrid, rowIndexes, section, applyScope, comparator, genWrappers.replaceOrInit, tableSection); return bundle(newGrid, details[0].row, details[0].column); }; const opMakeRowsHeader = makeRowsSection('thead', true); const opMakeRowsBody = makeRowsSection('tbody', false); const opMakeRowsFooter = makeRowsSection('tfoot', false); const opEraseColumns = (grid, extractDetail, _comparator, _genWrappers) => { const columns = uniqueColumns(extractDetail.details); const newGrid = deleteColumnsAt(grid, map$1(columns, column => column.column)); const maxColIndex = newGrid.length > 0 ? newGrid[0].cells.length - 1 : 0; return bundle(newGrid, columns[0].row, Math.min(columns[0].column, maxColIndex)); }; const opEraseRows = (grid, details, _comparator, _genWrappers) => { const rows = uniqueRows(details); const newGrid = deleteRowsAt(grid, rows[0].row, rows[rows.length - 1].row); const maxRowIndex = Math.max(extractGridDetails(newGrid).rows.length - 1, 0); return bundle(newGrid, Math.min(details[0].row, maxRowIndex), details[0].column); }; const opMergeCells = (grid, mergable, comparator, genWrappers) => { const cells = mergable.cells; merge(cells); const newGrid = merge$2(grid, mergable.bounds, comparator, genWrappers.merge(cells)); return outcome(newGrid, Optional.from(cells[0])); }; const opUnmergeCells = (grid, unmergable, comparator, genWrappers) => { const unmerge$1 = (b, cell) => unmerge(b, cell, comparator, genWrappers.unmerge(cell)); const newGrid = foldr(unmergable, unmerge$1, grid); return outcome(newGrid, Optional.from(unmergable[0])); }; const opPasteCells = (grid, pasteDetails, comparator, _genWrappers) => { const gridify = (table, generators) => { const wh = Warehouse.fromTable(table); return toGrid(wh, generators, true); }; const gridB = gridify(pasteDetails.clipboard, pasteDetails.generators); const startAddress = address(pasteDetails.row, pasteDetails.column); const mergedGrid = merge$1(startAddress, grid, gridB, pasteDetails.generators, comparator); return mergedGrid.fold(() => outcome(grid, Optional.some(pasteDetails.element)), newGrid => { return bundle(newGrid, pasteDetails.row, pasteDetails.column); }); }; const gridifyRows = (rows, generators, context) => { const pasteDetails = fromPastedRows(rows, context.section); const wh = Warehouse.generate(pasteDetails); return toGrid(wh, generators, true); }; const opPasteColsBefore = (grid, pasteDetails, comparator, _genWrappers) => { const rows = extractGridDetails(grid).rows; const index = pasteDetails.cells[0].column; const context = rows[pasteDetails.cells[0].row]; const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context); const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator); return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column); }; const opPasteColsAfter = (grid, pasteDetails, comparator, _genWrappers) => { const rows = extractGridDetails(grid).rows; const index = pasteDetails.cells[pasteDetails.cells.length - 1].column + pasteDetails.cells[pasteDetails.cells.length - 1].colspan; const context = rows[pasteDetails.cells[0].row]; const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context); const mergedGrid = insertCols(index, grid, gridB, pasteDetails.generators, comparator); return bundle(mergedGrid, pasteDetails.cells[0].row, index); }; const opPasteRowsBefore = (grid, pasteDetails, comparator, _genWrappers) => { const rows = extractGridDetails(grid).rows; const index = pasteDetails.cells[0].row; const context = rows[index]; const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context); const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator); return bundle(mergedGrid, pasteDetails.cells[0].row, pasteDetails.cells[0].column); }; const opPasteRowsAfter = (grid, pasteDetails, comparator, _genWrappers) => { const rows = extractGridDetails(grid).rows; const index = pasteDetails.cells[pasteDetails.cells.length - 1].row + pasteDetails.cells[pasteDetails.cells.length - 1].rowspan; const context = rows[pasteDetails.cells[0].row]; const gridB = gridifyRows(pasteDetails.clipboard, pasteDetails.generators, context); const mergedGrid = insertRows(index, grid, gridB, pasteDetails.generators, comparator); return bundle(mergedGrid, index, pasteDetails.cells[0].column); }; const opGetColumnsType = (table, target) => { const house = Warehouse.fromTable(table); const details = onCells(house, target); return details.bind(selectedCells => { const lastSelectedCell = selectedCells[selectedCells.length - 1]; const minColRange = selectedCells[0].column; const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan; const selectedColumnCells = flatten(map$1(house.all, row => filter$2(row.cells, cell => cell.column >= minColRange && cell.column < maxColRange))); return findCommonCellType(selectedColumnCells); }).getOr(''); }; const opGetCellsType = (table, target) => { const house = Warehouse.fromTable(table); const details = onCells(house, target); return details.bind(findCommonCellType).getOr(''); }; const opGetRowsType = (table, target) => { const house = Warehouse.fromTable(table); const details = onCells(house, target); return details.bind(selectedCells => { const lastSelectedCell = selectedCells[selectedCells.length - 1]; const minRowRange = selectedCells[0].row; const maxRowRange = lastSelectedCell.row + lastSelectedCell.rowspan; const selectedRows = house.all.slice(minRowRange, maxRowRange); return findCommonRowType(selectedRows); }).getOr(''); }; const resize = (table, list, details, behaviours) => adjustWidthTo(table, list, details, behaviours.sizing); const adjustAndRedistributeWidths = (table, list, details, behaviours) => adjustAndRedistributeWidths$1(table, list, details, behaviours.sizing, behaviours.resize); const firstColumnIsLocked = (_warehouse, details) => exists(details, detail => detail.column === 0 && detail.isLocked); const lastColumnIsLocked = (warehouse, details) => exists(details, detail => detail.column + detail.colspan >= warehouse.grid.columns && detail.isLocked); const getColumnsWidth = (warehouse, details) => { const columns$1 = columns(warehouse); const uniqueCols = uniqueColumns(details); return foldl(uniqueCols, (acc, detail) => { const column = columns$1[detail.column]; const colWidth = column.map(getOuter$2).getOr(0); return acc + colWidth; }, 0); }; const insertColumnsExtractor = before => (warehouse, target) => onCells(warehouse, target).filter(details => { const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked; return !checkLocked(warehouse, details); }).map(details => ({ details, pixelDelta: getColumnsWidth(warehouse, details) })); const eraseColumnsExtractor = (warehouse, target) => onUnlockedCells(warehouse, target).map(details => ({ details, pixelDelta: -getColumnsWidth(warehouse, details) })); const pasteColumnsExtractor = before => (warehouse, target) => onPasteByEditor(warehouse, target).filter(details => { const checkLocked = before ? firstColumnIsLocked : lastColumnIsLocked; return !checkLocked(warehouse, details.cells); }); const headerCellGenerator = Generators.transform('th'); const bodyCellGenerator = Generators.transform('td'); const insertRowsBefore = run(opInsertRowsBefore, onCells, noop, noop, Generators.modification); const insertRowsAfter = run(opInsertRowsAfter, onCells, noop, noop, Generators.modification); const insertColumnsBefore = run(opInsertColumnsBefore, insertColumnsExtractor(true), adjustAndRedistributeWidths, noop, Generators.modification); const insertColumnsAfter = run(opInsertColumnsAfter, insertColumnsExtractor(false), adjustAndRedistributeWidths, noop, Generators.modification); const eraseColumns = run(opEraseColumns, eraseColumnsExtractor, adjustAndRedistributeWidths, prune, Generators.modification); const eraseRows = run(opEraseRows, onCells, noop, prune, Generators.modification); const makeColumnsHeader = run(opMakeColumnsHeader, onUnlockedCells, noop, noop, headerCellGenerator); const unmakeColumnsHeader = run(opUnmakeColumnsHeader, onUnlockedCells, noop, noop, bodyCellGenerator); const makeRowsHeader = run(opMakeRowsHeader, onCells, noop, noop, headerCellGenerator); const makeRowsBody = run(opMakeRowsBody, onCells, noop, noop, bodyCellGenerator); const makeRowsFooter = run(opMakeRowsFooter, onCells, noop, noop, bodyCellGenerator); const makeCellsHeader = run(opMakeCellsHeader, onUnlockedCells, noop, noop, headerCellGenerator); const unmakeCellsHeader = run(opUnmakeCellsHeader, onUnlockedCells, noop, noop, bodyCellGenerator); const mergeCells = run(opMergeCells, onUnlockedMergable, resize, noop, Generators.merging); const unmergeCells = run(opUnmergeCells, onUnlockedUnmergable, resize, noop, Generators.merging); const pasteCells = run(opPasteCells, onPaste, resize, noop, Generators.modification); const pasteColsBefore = run(opPasteColsBefore, pasteColumnsExtractor(true), noop, noop, Generators.modification); const pasteColsAfter = run(opPasteColsAfter, pasteColumnsExtractor(false), noop, noop, Generators.modification); const pasteRowsBefore = run(opPasteRowsBefore, onPasteByEditor, noop, noop, Generators.modification); const pasteRowsAfter = run(opPasteRowsAfter, onPasteByEditor, noop, noop, Generators.modification); const getColumnsType = opGetColumnsType; const getCellsType = opGetCellsType; const getRowsType = opGetRowsType; const fireNewRow = (editor, row) => editor.dispatch('NewRow', { node: row }); const fireNewCell = (editor, cell) => editor.dispatch('NewCell', { node: cell }); const fireTableModified = (editor, table, data) => { editor.dispatch('TableModified', { ...data, table }); }; const fireTableSelectionChange = (editor, cells, start, finish, otherCells) => { editor.dispatch('TableSelectionChange', { cells, start, finish, otherCells }); }; const fireTableSelectionClear = editor => { editor.dispatch('TableSelectionClear'); }; const fireObjectResizeStart = (editor, target, width, height, origin) => { editor.dispatch('ObjectResizeStart', { target, width, height, origin }); }; const fireObjectResized = (editor, target, width, height, origin) => { editor.dispatch('ObjectResized', { target, width, height, origin }); }; const styleModified = { structure: false, style: true }; const structureModified = { structure: true, style: false }; const styleAndStructureModified = { structure: true, style: true }; const get$5 = (editor, table) => { if (isTablePercentagesForced(editor)) { return TableSize.percentageSize(table); } else if (isTablePixelsForced(editor)) { return TableSize.pixelSize(table); } else { return TableSize.getTableSize(table); } }; const TableActions = (editor, resizeHandler, cellSelectionHandler) => { const isTableBody = editor => name(getBody(editor)) === 'table'; const lastRowGuard = table => !isTableBody(editor) || getGridSize(table).rows > 1; const lastColumnGuard = table => !isTableBody(editor) || getGridSize(table).columns > 1; const cloneFormats = getTableCloneElements(editor); const colMutationOp = isResizeTableColumnResizing(editor) ? noop : halve; const getTableSectionType = table => { switch (getTableHeaderType(editor)) { case 'section': return TableSection.section(); case 'sectionCells': return TableSection.sectionCells(); case 'cells': return TableSection.cells(); default: return TableSection.getTableSectionType(table, 'section'); } }; const setSelectionFromAction = (table, result) => result.cursor.fold(() => { const cells = cells$1(table); return head(cells).filter(inBody).map(firstCell => { cellSelectionHandler.clearSelectedCells(table.dom); const rng = editor.dom.createRng(); rng.selectNode(firstCell.dom); editor.selection.setRng(rng); set$2(firstCell, 'data-mce-selected', '1'); return rng; }); }, cell => { const des = freefallRtl(cell); const rng = editor.dom.createRng(); rng.setStart(des.element.dom, des.offset); rng.setEnd(des.element.dom, des.offset); editor.selection.setRng(rng); cellSelectionHandler.clearSelectedCells(table.dom); return Optional.some(rng); }); const execute = (operation, guard, mutate, effect) => (table, target, noEvents = false) => { removeDataStyle(table); const doc = SugarElement.fromDom(editor.getDoc()); const generators = cellOperations(mutate, doc, cloneFormats); const behaviours = { sizing: get$5(editor, table), resize: isResizeTableColumnResizing(editor) ? resizeTable() : preserveTable(), section: getTableSectionType(table) }; return guard(table) ? operation(table, target, generators, behaviours).bind(result => { resizeHandler.refresh(table.dom); each$2(result.newRows, row => { fireNewRow(editor, row.dom); }); each$2(result.newCells, cell => { fireNewCell(editor, cell.dom); }); const range = setSelectionFromAction(table, result); if (inBody(table)) { removeDataStyle(table); if (!noEvents) { fireTableModified(editor, table.dom, effect); } } return range.map(rng => ({ rng, effect })); }) : Optional.none(); }; const deleteRow = execute(eraseRows, lastRowGuard, noop, structureModified); const deleteColumn = execute(eraseColumns, lastColumnGuard, noop, structureModified); const insertRowsBefore$1 = execute(insertRowsBefore, always, noop, structureModified); const insertRowsAfter$1 = execute(insertRowsAfter, always, noop, structureModified); const insertColumnsBefore$1 = execute(insertColumnsBefore, always, colMutationOp, structureModified); const insertColumnsAfter$1 = execute(insertColumnsAfter, always, colMutationOp, structureModified); const mergeCells$1 = execute(mergeCells, always, noop, structureModified); const unmergeCells$1 = execute(unmergeCells, always, noop, structureModified); const pasteColsBefore$1 = execute(pasteColsBefore, always, noop, structureModified); const pasteColsAfter$1 = execute(pasteColsAfter, always, noop, structureModified); const pasteRowsBefore$1 = execute(pasteRowsBefore, always, noop, structureModified); const pasteRowsAfter$1 = execute(pasteRowsAfter, always, noop, structureModified); const pasteCells$1 = execute(pasteCells, always, noop, styleAndStructureModified); const makeCellsHeader$1 = execute(makeCellsHeader, always, noop, structureModified); const unmakeCellsHeader$1 = execute(unmakeCellsHeader, always, noop, structureModified); const makeColumnsHeader$1 = execute(makeColumnsHeader, always, noop, structureModified); const unmakeColumnsHeader$1 = execute(unmakeColumnsHeader, always, noop, structureModified); const makeRowsHeader$1 = execute(makeRowsHeader, always, noop, structureModified); const makeRowsBody$1 = execute(makeRowsBody, always, noop, structureModified); const makeRowsFooter$1 = execute(makeRowsFooter, always, noop, structureModified); const getTableCellType = getCellsType; const getTableColType = getColumnsType; const getTableRowType = getRowsType; return { deleteRow, deleteColumn, insertRowsBefore: insertRowsBefore$1, insertRowsAfter: insertRowsAfter$1, insertColumnsBefore: insertColumnsBefore$1, insertColumnsAfter: insertColumnsAfter$1, mergeCells: mergeCells$1, unmergeCells: unmergeCells$1, pasteColsBefore: pasteColsBefore$1, pasteColsAfter: pasteColsAfter$1, pasteRowsBefore: pasteRowsBefore$1, pasteRowsAfter: pasteRowsAfter$1, pasteCells: pasteCells$1, makeCellsHeader: makeCellsHeader$1, unmakeCellsHeader: unmakeCellsHeader$1, makeColumnsHeader: makeColumnsHeader$1, unmakeColumnsHeader: unmakeColumnsHeader$1, makeRowsHeader: makeRowsHeader$1, makeRowsBody: makeRowsBody$1, makeRowsFooter: makeRowsFooter$1, getTableRowType, getTableCellType, getTableColType }; }; const constrainSpan = (element, property, value) => { const currentColspan = getAttrValue(element, property, 1); if (value === 1 || currentColspan <= 1) { remove$7(element, property); } else { set$2(element, property, Math.min(value, currentColspan)); } }; const isColInRange = (minColRange, maxColRange) => cell => { const endCol = cell.column + cell.colspan - 1; const startCol = cell.column; return endCol >= minColRange && startCol < maxColRange; }; const generateColGroup = (house, minColRange, maxColRange) => { if (Warehouse.hasColumns(house)) { const colsToCopy = filter$2(Warehouse.justColumns(house), isColInRange(minColRange, maxColRange)); const copiedCols = map$1(colsToCopy, c => { const clonedCol = deep(c.element); constrainSpan(clonedCol, 'span', maxColRange - minColRange); return clonedCol; }); const fakeColgroup = SugarElement.fromTag('colgroup'); append(fakeColgroup, copiedCols); return [fakeColgroup]; } else { return []; } }; const generateRows = (house, minColRange, maxColRange) => map$1(house.all, row => { const cellsToCopy = filter$2(row.cells, isColInRange(minColRange, maxColRange)); const copiedCells = map$1(cellsToCopy, cell => { const clonedCell = deep(cell.element); constrainSpan(clonedCell, 'colspan', maxColRange - minColRange); return clonedCell; }); const fakeTR = SugarElement.fromTag('tr'); append(fakeTR, copiedCells); return fakeTR; }); const copyCols = (table, target) => { const house = Warehouse.fromTable(table); const details = onUnlockedCells(house, target); return details.map(selectedCells => { const lastSelectedCell = selectedCells[selectedCells.length - 1]; const minColRange = selectedCells[0].column; const maxColRange = lastSelectedCell.column + lastSelectedCell.colspan; const fakeColGroups = generateColGroup(house, minColRange, maxColRange); const fakeRows = generateRows(house, minColRange, maxColRange); return [ ...fakeColGroups, ...fakeRows ]; }); }; const copyRows = (table, target, generators) => { const warehouse = Warehouse.fromTable(table); const details = onCells(warehouse, target); return details.bind(selectedCells => { const grid = toGrid(warehouse, generators, false); const rows = extractGridDetails(grid).rows; const slicedGrid = rows.slice(selectedCells[0].row, selectedCells[selectedCells.length - 1].row + selectedCells[selectedCells.length - 1].rowspan); const filteredGrid = bind$2(slicedGrid, row => { const newCells = filter$2(row.cells, cell => !cell.isLocked); return newCells.length > 0 ? [{ ...row, cells: newCells }] : []; }); const slicedDetails = toDetailList(filteredGrid); return someIf(slicedDetails.length > 0, slicedDetails); }).map(slicedDetails => copy(slicedDetails)); }; const adt$5 = Adt.generate([ { invalid: ['raw'] }, { pixels: ['value'] }, { percent: ['value'] } ]); const validateFor = (suffix, type, value) => { const rawAmount = value.substring(0, value.length - suffix.length); const amount = parseFloat(rawAmount); return rawAmount === amount.toString() ? type(amount) : adt$5.invalid(value); }; const from = value => { if (endsWith(value, '%')) { return validateFor('%', adt$5.percent, value); } if (endsWith(value, 'px')) { return validateFor('px', adt$5.pixels, value); } return adt$5.invalid(value); }; const Size = { ...adt$5, from }; const redistributeToPercent = (widths, totalWidth) => { return map$1(widths, w => { const colType = Size.from(w); return colType.fold(() => { return w; }, px => { const ratio = px / totalWidth * 100; return ratio + '%'; }, pc => { return pc + '%'; }); }); }; const redistributeToPx = (widths, totalWidth, newTotalWidth) => { const scale = newTotalWidth / totalWidth; return map$1(widths, w => { const colType = Size.from(w); return colType.fold(() => { return w; }, px => { return px * scale + 'px'; }, pc => { return pc / 100 * newTotalWidth + 'px'; }); }); }; const redistributeEmpty = (newWidthType, columns) => { const f = newWidthType.fold(() => constant(''), pixels => { const num = pixels / columns; return constant(num + 'px'); }, () => { const num = 100 / columns; return constant(num + '%'); }); return range$1(columns, f); }; const redistributeValues = (newWidthType, widths, totalWidth) => { return newWidthType.fold(() => { return widths; }, px => { return redistributeToPx(widths, totalWidth, px); }, _pc => { return redistributeToPercent(widths, totalWidth); }); }; const redistribute$1 = (widths, totalWidth, newWidth) => { const newType = Size.from(newWidth); const floats = forall(widths, s => { return s === '0px'; }) ? redistributeEmpty(newType, widths.length) : redistributeValues(newType, widths, totalWidth); return normalize(floats); }; const sum = (values, fallback) => { if (values.length === 0) { return fallback; } return foldr(values, (rest, v) => { return Size.from(v).fold(constant(0), identity, identity) + rest; }, 0); }; const roundDown = (num, unit) => { const floored = Math.floor(num); return { value: floored + unit, remainder: num - floored }; }; const add$3 = (value, amount) => { return Size.from(value).fold(constant(value), px => { return px + amount + 'px'; }, pc => { return pc + amount + '%'; }); }; const normalize = values => { if (values.length === 0) { return values; } const scan = foldr(values, (rest, value) => { const info = Size.from(value).fold(() => ({ value, remainder: 0 }), num => roundDown(num, 'px'), num => ({ value: num + '%', remainder: 0 })); return { output: [info.value].concat(rest.output), remainder: rest.remainder + info.remainder }; }, { output: [], remainder: 0 }); const r = scan.output; return r.slice(0, r.length - 1).concat([add$3(r[r.length - 1], Math.round(scan.remainder))]); }; const validate = Size.from; const redistributeToW = (newWidths, cells, unit) => { each$2(cells, cell => { const widths = newWidths.slice(cell.column, cell.colspan + cell.column); const w = sum(widths, minWidth()); set$1(cell.element, 'width', w + unit); }); }; const redistributeToColumns = (newWidths, columns, unit) => { each$2(columns, (column, index) => { const width = sum([newWidths[index]], minWidth()); set$1(column.element, 'width', width + unit); }); }; const redistributeToH = (newHeights, rows, cells) => { each$2(cells, cell => { remove$5(cell.element, 'height'); }); each$2(rows, (row, i) => { set$1(row.element, 'height', newHeights[i]); }); }; const getUnit = newSize => { return validate(newSize).fold(constant('px'), constant('px'), constant('%')); }; const redistribute = (table, optWidth, optHeight) => { const warehouse = Warehouse.fromTable(table); const rows = warehouse.all; const cells = Warehouse.justCells(warehouse); const columns = Warehouse.justColumns(warehouse); optWidth.each(newWidth => { const widthUnit = getUnit(newWidth); const totalWidth = get$9(table); const oldWidths = getRawWidths(warehouse, table); const nuWidths = redistribute$1(oldWidths, totalWidth, newWidth); if (Warehouse.hasColumns(warehouse)) { redistributeToColumns(nuWidths, columns, widthUnit); } else { redistributeToW(nuWidths, cells, widthUnit); } set$1(table, 'width', newWidth); }); optHeight.each(newHeight => { const totalHeight = get$8(table); const oldHeights = getRawHeights(warehouse, table); const nuHeights = redistribute$1(oldHeights, totalHeight, newHeight); redistributeToH(nuHeights, rows, cells); set$1(table, 'height', newHeight); }); }; const isPercentSizing = isPercentSizing$1; const isPixelSizing = isPixelSizing$1; const isNoneSizing = isNoneSizing$1; const cleanupLegacyAttributes = element => { remove$7(element, 'width'); remove$7(element, 'height'); }; const convertToPercentSizeWidth = table => { const newWidth = getPercentTableWidth(table); redistribute(table, Optional.some(newWidth), Optional.none()); cleanupLegacyAttributes(table); }; const convertToPixelSizeWidth = table => { const newWidth = getPixelTableWidth(table); redistribute(table, Optional.some(newWidth), Optional.none()); cleanupLegacyAttributes(table); }; const convertToPixelSizeHeight = table => { const newHeight = getPixelTableHeight(table); redistribute(table, Optional.none(), Optional.some(newHeight)); cleanupLegacyAttributes(table); }; const convertToNoneSizeWidth = table => { remove$5(table, 'width'); const columns = columns$1(table); const rowElements = columns.length > 0 ? columns : cells$1(table); each$2(rowElements, cell => { remove$5(cell, 'width'); cleanupLegacyAttributes(cell); }); cleanupLegacyAttributes(table); }; const DefaultRenderOptions = { styles: { 'border-collapse': 'collapse', 'width': '100%' }, attributes: { border: '1' }, colGroups: false }; const tableHeaderCell = () => SugarElement.fromTag('th'); const tableCell = () => SugarElement.fromTag('td'); const tableColumn = () => SugarElement.fromTag('col'); const createRow = (columns, rowHeaders, columnHeaders, rowIndex) => { const tr = SugarElement.fromTag('tr'); for (let j = 0; j < columns; j++) { const td = rowIndex < rowHeaders || j < columnHeaders ? tableHeaderCell() : tableCell(); if (j < columnHeaders) { set$2(td, 'scope', 'row'); } if (rowIndex < rowHeaders) { set$2(td, 'scope', 'col'); } append$1(td, SugarElement.fromTag('br')); append$1(tr, td); } return tr; }; const createGroupRow = columns => { const columnGroup = SugarElement.fromTag('colgroup'); range$1(columns, () => append$1(columnGroup, tableColumn())); return columnGroup; }; const createRows = (rows, columns, rowHeaders, columnHeaders) => range$1(rows, r => createRow(columns, rowHeaders, columnHeaders, r)); const render = (rows, columns, rowHeaders, columnHeaders, headerType, renderOpts = DefaultRenderOptions) => { const table = SugarElement.fromTag('table'); const rowHeadersGoInThead = headerType !== 'cells'; setAll(table, renderOpts.styles); setAll$1(table, renderOpts.attributes); if (renderOpts.colGroups) { append$1(table, createGroupRow(columns)); } const actualRowHeaders = Math.min(rows, rowHeaders); if (rowHeadersGoInThead && rowHeaders > 0) { const thead = SugarElement.fromTag('thead'); append$1(table, thead); const theadRowHeaders = headerType === 'sectionCells' ? actualRowHeaders : 0; const theadRows = createRows(rowHeaders, columns, theadRowHeaders, columnHeaders); append(thead, theadRows); } const tbody = SugarElement.fromTag('tbody'); append$1(table, tbody); const numRows = rowHeadersGoInThead ? rows - actualRowHeaders : rows; const numRowHeaders = rowHeadersGoInThead ? 0 : rowHeaders; const tbodyRows = createRows(numRows, columns, numRowHeaders, columnHeaders); append(tbody, tbodyRows); return table; }; const get$4 = element => element.dom.innerHTML; const getOuter = element => { const container = SugarElement.fromTag('div'); const clone = SugarElement.fromDom(element.dom.cloneNode(true)); append$1(container, clone); return get$4(container); }; const placeCaretInCell = (editor, cell) => { editor.selection.select(cell.dom, true); editor.selection.collapse(true); }; const selectFirstCellInTable = (editor, tableElm) => { descendant(tableElm, 'td,th').each(curry(placeCaretInCell, editor)); }; const fireEvents = (editor, table) => { each$2(descendants(table, 'tr'), row => { fireNewRow(editor, row.dom); each$2(descendants(row, 'th,td'), cell => { fireNewCell(editor, cell.dom); }); }); }; const isPercentage = width => isString(width) && width.indexOf('%') !== -1; const insert = (editor, columns, rows, colHeaders, rowHeaders) => { const defaultStyles = getTableDefaultStyles(editor); const options = { styles: defaultStyles, attributes: getTableDefaultAttributes(editor), colGroups: tableUseColumnGroup(editor) }; editor.undoManager.ignore(() => { const table = render(rows, columns, rowHeaders, colHeaders, getTableHeaderType(editor), options); set$2(table, 'data-mce-id', '__mce'); const html = getOuter(table); editor.insertContent(html); editor.addVisual(); }); return descendant(getBody(editor), 'table[data-mce-id="__mce"]').map(table => { if (isTablePixelsForced(editor)) { convertToPixelSizeWidth(table); } else if (isTableResponsiveForced(editor)) { convertToNoneSizeWidth(table); } else if (isTablePercentagesForced(editor) || isPercentage(defaultStyles.width)) { convertToPercentSizeWidth(table); } removeDataStyle(table); remove$7(table, 'data-mce-id'); fireEvents(editor, table); selectFirstCellInTable(editor, table); return table.dom; }).getOrNull(); }; const insertTable = (editor, rows, columns, options = {}) => { const checkInput = val => isNumber(val) && val > 0; if (checkInput(rows) && checkInput(columns)) { const headerRows = options.headerRows || 0; const headerColumns = options.headerColumns || 0; return insert(editor, columns, rows, headerColumns, headerRows); } else { console.error('Invalid values for mceInsertTable - rows and columns values are required to insert a table.'); return null; } }; var global = tinymce.util.Tools.resolve('tinymce.FakeClipboard'); const tableTypeBase = 'x-tinymce/dom-table-'; const tableTypeRow = tableTypeBase + 'rows'; const tableTypeColumn = tableTypeBase + 'columns'; const setData = items => { const fakeClipboardItem = global.FakeClipboardItem(items); global.write([fakeClipboardItem]); }; const getData = type => { var _a; const items = (_a = global.read()) !== null && _a !== void 0 ? _a : []; return findMap(items, item => Optional.from(item.getType(type))); }; const clearData = type => { if (getData(type).isSome()) { global.clear(); } }; const setRows = rowsOpt => { rowsOpt.fold(clearRows, rows => setData({ [tableTypeRow]: rows })); }; const getRows = () => getData(tableTypeRow); const clearRows = () => clearData(tableTypeRow); const setColumns = columnsOpt => { columnsOpt.fold(clearColumns, columns => setData({ [tableTypeColumn]: columns })); }; const getColumns = () => getData(tableTypeColumn); const clearColumns = () => clearData(tableTypeColumn); const getSelectionStartCellOrCaption = editor => getSelectionCellOrCaption(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1); const getSelectionStartCell = editor => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)).filter(isInEditableContext$1); const registerCommands = (editor, actions) => { const isRoot = getIsRoot(editor); const eraseTable = () => getSelectionStartCellOrCaption(editor).each(cellOrCaption => { table(cellOrCaption, isRoot).filter(not(isRoot)).each(table => { const cursor = SugarElement.fromText(''); after$5(table, cursor); remove$6(table); if (editor.dom.isEmpty(editor.getBody())) { editor.setContent(''); editor.selection.setCursorLocation(); } else { const rng = editor.dom.createRng(); rng.setStart(cursor.dom, 0); rng.setEnd(cursor.dom, 0); editor.selection.setRng(rng); editor.nodeChanged(); } }); }); const setSizingMode = sizing => getSelectionStartCellOrCaption(editor).each(cellOrCaption => { const isForcedSizing = isTableResponsiveForced(editor) || isTablePixelsForced(editor) || isTablePercentagesForced(editor); if (!isForcedSizing) { table(cellOrCaption, isRoot).each(table => { if (sizing === 'relative' && !isPercentSizing(table)) { convertToPercentSizeWidth(table); } else if (sizing === 'fixed' && !isPixelSizing(table)) { convertToPixelSizeWidth(table); } else if (sizing === 'responsive' && !isNoneSizing(table)) { convertToNoneSizeWidth(table); } removeDataStyle(table); fireTableModified(editor, table.dom, structureModified); }); } }); const getTableFromCell = cell => table(cell, isRoot); const performActionOnSelection = action => getSelectionStartCell(editor).bind(cell => getTableFromCell(cell).map(table => action(table, cell))); const toggleTableClass = (_ui, clazz) => { performActionOnSelection(table => { editor.formatter.toggle('tableclass', { value: clazz }, table.dom); fireTableModified(editor, table.dom, styleModified); }); }; const toggleTableCellClass = (_ui, clazz) => { performActionOnSelection(table => { const selectedCells = getCellsFromSelection(editor); const allHaveClass = forall(selectedCells, cell => editor.formatter.match('tablecellclass', { value: clazz }, cell.dom)); const formatterAction = allHaveClass ? editor.formatter.remove : editor.formatter.apply; each$2(selectedCells, cell => formatterAction('tablecellclass', { value: clazz }, cell.dom)); fireTableModified(editor, table.dom, styleModified); }); }; const toggleCaption = () => { getSelectionStartCellOrCaption(editor).each(cellOrCaption => { table(cellOrCaption, isRoot).each(table => { child(table, 'caption').fold(() => { const caption = SugarElement.fromTag('caption'); append$1(caption, SugarElement.fromText('Caption')); appendAt(table, caption, 0); editor.selection.setCursorLocation(caption.dom, 0); }, caption => { if (isTag('caption')(cellOrCaption)) { one('td', table).each(td => editor.selection.setCursorLocation(td.dom, 0)); } remove$6(caption); }); fireTableModified(editor, table.dom, structureModified); }); }); }; const postExecute = _data => { editor.focus(); }; const actOnSelection = (execute, noEvents = false) => performActionOnSelection((table, startCell) => { const targets = forMenu(getCellsFromSelection(editor), table, startCell); execute(table, targets, noEvents).each(postExecute); }); const copyRowSelection = () => performActionOnSelection((table, startCell) => { const targets = forMenu(getCellsFromSelection(editor), table, startCell); const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), Optional.none()); return copyRows(table, targets, generators); }); const copyColSelection = () => performActionOnSelection((table, startCell) => { const targets = forMenu(getCellsFromSelection(editor), table, startCell); return copyCols(table, targets); }); const pasteOnSelection = (execute, getRows) => getRows().each(rows => { const clonedRows = map$1(rows, row => deep(row)); performActionOnSelection((table, startCell) => { const generators = paste$1(SugarElement.fromDom(editor.getDoc())); const targets = pasteRows(getCellsFromSelection(editor), startCell, clonedRows, generators); execute(table, targets).each(postExecute); }); }); const actOnType = getAction => (_ui, args) => get$c(args, 'type').each(type => { actOnSelection(getAction(type), args.no_events); }); each$1({ mceTableSplitCells: () => actOnSelection(actions.unmergeCells), mceTableMergeCells: () => actOnSelection(actions.mergeCells), mceTableInsertRowBefore: () => actOnSelection(actions.insertRowsBefore), mceTableInsertRowAfter: () => actOnSelection(actions.insertRowsAfter), mceTableInsertColBefore: () => actOnSelection(actions.insertColumnsBefore), mceTableInsertColAfter: () => actOnSelection(actions.insertColumnsAfter), mceTableDeleteCol: () => actOnSelection(actions.deleteColumn), mceTableDeleteRow: () => actOnSelection(actions.deleteRow), mceTableCutCol: () => copyColSelection().each(selection => { setColumns(selection); actOnSelection(actions.deleteColumn); }), mceTableCutRow: () => copyRowSelection().each(selection => { setRows(selection); actOnSelection(actions.deleteRow); }), mceTableCopyCol: () => copyColSelection().each(selection => setColumns(selection)), mceTableCopyRow: () => copyRowSelection().each(selection => setRows(selection)), mceTablePasteColBefore: () => pasteOnSelection(actions.pasteColsBefore, getColumns), mceTablePasteColAfter: () => pasteOnSelection(actions.pasteColsAfter, getColumns), mceTablePasteRowBefore: () => pasteOnSelection(actions.pasteRowsBefore, getRows), mceTablePasteRowAfter: () => pasteOnSelection(actions.pasteRowsAfter, getRows), mceTableDelete: eraseTable, mceTableCellToggleClass: toggleTableCellClass, mceTableToggleClass: toggleTableClass, mceTableToggleCaption: toggleCaption, mceTableSizingMode: (_ui, sizing) => setSizingMode(sizing), mceTableCellType: actOnType(type => type === 'th' ? actions.makeCellsHeader : actions.unmakeCellsHeader), mceTableColType: actOnType(type => type === 'th' ? actions.makeColumnsHeader : actions.unmakeColumnsHeader), mceTableRowType: actOnType(type => { switch (type) { case 'header': return actions.makeRowsHeader; case 'footer': return actions.makeRowsFooter; default: return actions.makeRowsBody; } }) }, (func, name) => editor.addCommand(name, func)); editor.addCommand('mceInsertTable', (_ui, args) => { insertTable(editor, args.rows, args.columns, args.options); }); editor.addCommand('mceTableApplyCellStyle', (_ui, args) => { const getFormatName = style => 'tablecell' + style.toLowerCase().replace('-', ''); if (!isObject(args)) { return; } const cells = filter$2(getCellsFromSelection(editor), isInEditableContext$1); if (cells.length === 0) { return; } const validArgs = filter$1(args, (value, style) => editor.formatter.has(getFormatName(style)) && isString(value)); if (isEmpty(validArgs)) { return; } each$1(validArgs, (value, style) => { const formatName = getFormatName(style); each$2(cells, cell => { if (value === '') { editor.formatter.remove(formatName, { value: null }, cell.dom, true); } else { editor.formatter.apply(formatName, { value }, cell.dom); } }); }); getTableFromCell(cells[0]).each(table => fireTableModified(editor, table.dom, styleModified)); }); }; const registerQueryCommands = (editor, actions) => { const isRoot = getIsRoot(editor); const lookupOnSelection = action => getSelectionCell(getSelectionStart(editor)).bind(cell => table(cell, isRoot).map(table => { const targets = forMenu(getCellsFromSelection(editor), table, cell); return action(table, targets); })).getOr(''); each$1({ mceTableRowType: () => lookupOnSelection(actions.getTableRowType), mceTableCellType: () => lookupOnSelection(actions.getTableCellType), mceTableColType: () => lookupOnSelection(actions.getTableColType) }, (func, name) => editor.addQueryValueHandler(name, func)); }; const adt$4 = Adt.generate([ { before: ['element'] }, { on: [ 'element', 'offset' ] }, { after: ['element'] } ]); const cata$1 = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter); const getStart$1 = situ => situ.fold(identity, identity, identity); const before$2 = adt$4.before; const on = adt$4.on; const after$3 = adt$4.after; const Situ = { before: before$2, on, after: after$3, cata: cata$1, getStart: getStart$1 }; const create$4 = (selection, kill) => ({ selection, kill }); const Response = { create: create$4 }; const selectNode = (win, element) => { const rng = win.document.createRange(); rng.selectNode(element.dom); return rng; }; const selectNodeContents = (win, element) => { const rng = win.document.createRange(); selectNodeContentsUsing(rng, element); return rng; }; const selectNodeContentsUsing = (rng, element) => rng.selectNodeContents(element.dom); const setStart = (rng, situ) => { situ.fold(e => { rng.setStartBefore(e.dom); }, (e, o) => { rng.setStart(e.dom, o); }, e => { rng.setStartAfter(e.dom); }); }; const setFinish = (rng, situ) => { situ.fold(e => { rng.setEndBefore(e.dom); }, (e, o) => { rng.setEnd(e.dom, o); }, e => { rng.setEndAfter(e.dom); }); }; const relativeToNative = (win, startSitu, finishSitu) => { const range = win.document.createRange(); setStart(range, startSitu); setFinish(range, finishSitu); return range; }; const exactToNative = (win, start, soffset, finish, foffset) => { const rng = win.document.createRange(); rng.setStart(start.dom, soffset); rng.setEnd(finish.dom, foffset); return rng; }; const toRect = rect => ({ left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom, width: rect.width, height: rect.height }); const getFirstRect$1 = rng => { const rects = rng.getClientRects(); const rect = rects.length > 0 ? rects[0] : rng.getBoundingClientRect(); return rect.width > 0 || rect.height > 0 ? Optional.some(rect).map(toRect) : Optional.none(); }; const adt$3 = Adt.generate([ { ltr: [ 'start', 'soffset', 'finish', 'foffset' ] }, { rtl: [ 'start', 'soffset', 'finish', 'foffset' ] } ]); const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset); const getRanges = (win, selection) => selection.match({ domRange: rng => { return { ltr: constant(rng), rtl: Optional.none }; }, relative: (startSitu, finishSitu) => { return { ltr: cached(() => relativeToNative(win, startSitu, finishSitu)), rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu))) }; }, exact: (start, soffset, finish, foffset) => { return { ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)), rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset))) }; } }); const doDiagnose = (win, ranges) => { const rng = ranges.ltr(); if (rng.collapsed) { const reversed = ranges.rtl().filter(rev => rev.collapsed === false); return reversed.map(rev => adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$3.ltr, rng)); } else { return fromRange(win, adt$3.ltr, rng); } }; const diagnose = (win, selection) => { const ranges = getRanges(win, selection); return doDiagnose(win, ranges); }; const asLtrRange = (win, selection) => { const diagnosis = diagnose(win, selection); return diagnosis.match({ ltr: (start, soffset, finish, foffset) => { const rng = win.document.createRange(); rng.setStart(start.dom, soffset); rng.setEnd(finish.dom, foffset); return rng; }, rtl: (start, soffset, finish, foffset) => { const rng = win.document.createRange(); rng.setStart(finish.dom, foffset); rng.setEnd(start.dom, soffset); return rng; } }); }; adt$3.ltr; adt$3.rtl; const create$3 = (start, soffset, finish, foffset) => ({ start, soffset, finish, foffset }); const SimRange = { create: create$3 }; const create$2 = (start, soffset, finish, foffset) => { return { start: Situ.on(start, soffset), finish: Situ.on(finish, foffset) }; }; const Situs = { create: create$2 }; const convertToRange = (win, selection) => { const rng = asLtrRange(win, selection); return SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset); }; const makeSitus = Situs.create; const sync = (container, isRoot, start, soffset, finish, foffset, selectRange) => { if (!(eq$1(start, finish) && soffset === foffset)) { return closest$1(start, 'td,th', isRoot).bind(s => { return closest$1(finish, 'td,th', isRoot).bind(f => { return detect(container, isRoot, s, f, selectRange); }); }); } else { return Optional.none(); } }; const detect = (container, isRoot, start, finish, selectRange) => { if (!eq$1(start, finish)) { return identify(start, finish, isRoot).bind(cellSel => { const boxes = cellSel.boxes.getOr([]); if (boxes.length > 1) { selectRange(container, boxes, cellSel.start, cellSel.finish); return Optional.some(Response.create(Optional.some(makeSitus(start, 0, start, getEnd(start))), true)); } else { return Optional.none(); } }); } else { return Optional.none(); } }; const update = (rows, columns, container, selected, annotations) => { const updateSelection = newSels => { annotations.clearBeforeUpdate(container); annotations.selectRange(container, newSels.boxes, newSels.start, newSels.finish); return newSels.boxes; }; return shiftSelection(selected, rows, columns, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(updateSelection); }; const traverse = (item, mode) => ({ item, mode }); const backtrack = (universe, item, _direction, transition = sidestep) => { return universe.property().parent(item).map(p => { return traverse(p, transition); }); }; const sidestep = (universe, item, direction, transition = advance) => { return direction.sibling(universe, item).map(p => { return traverse(p, transition); }); }; const advance = (universe, item, direction, transition = advance) => { const children = universe.property().children(item); const result = direction.first(children); return result.map(r => { return traverse(r, transition); }); }; const successors = [ { current: backtrack, next: sidestep, fallback: Optional.none() }, { current: sidestep, next: advance, fallback: Optional.some(backtrack) }, { current: advance, next: advance, fallback: Optional.some(sidestep) } ]; const go = (universe, item, mode, direction, rules = successors) => { const ruleOpt = find$1(rules, succ => { return succ.current === mode; }); return ruleOpt.bind(rule => { return rule.current(universe, item, direction, rule.next).orThunk(() => { return rule.fallback.bind(fb => { return go(universe, item, fb, direction); }); }); }); }; const left$1 = () => { const sibling = (universe, item) => { return universe.query().prevSibling(item); }; const first = children => { return children.length > 0 ? Optional.some(children[children.length - 1]) : Optional.none(); }; return { sibling, first }; }; const right$1 = () => { const sibling = (universe, item) => { return universe.query().nextSibling(item); }; const first = children => { return children.length > 0 ? Optional.some(children[0]) : Optional.none(); }; return { sibling, first }; }; const Walkers = { left: left$1, right: right$1 }; const hone = (universe, item, predicate, mode, direction, isRoot) => { const next = go(universe, item, mode, direction); return next.bind(n => { if (isRoot(n.item)) { return Optional.none(); } else { return predicate(n.item) ? Optional.some(n.item) : hone(universe, n.item, predicate, n.mode, direction, isRoot); } }); }; const left = (universe, item, predicate, isRoot) => { return hone(universe, item, predicate, sidestep, Walkers.left(), isRoot); }; const right = (universe, item, predicate, isRoot) => { return hone(universe, item, predicate, sidestep, Walkers.right(), isRoot); }; const isLeaf = universe => element => universe.property().children(element).length === 0; const before$1 = (universe, item, isRoot) => { return seekLeft$1(universe, item, isLeaf(universe), isRoot); }; const after$2 = (universe, item, isRoot) => { return seekRight$1(universe, item, isLeaf(universe), isRoot); }; const seekLeft$1 = left; const seekRight$1 = right; const universe = DomUniverse(); const before = (element, isRoot) => { return before$1(universe, element, isRoot); }; const after$1 = (element, isRoot) => { return after$2(universe, element, isRoot); }; const seekLeft = (element, predicate, isRoot) => { return seekLeft$1(universe, element, predicate, isRoot); }; const seekRight = (element, predicate, isRoot) => { return seekRight$1(universe, element, predicate, isRoot); }; const ancestor = (scope, predicate, isRoot) => ancestor$2(scope, predicate, isRoot).isSome(); const adt$2 = Adt.generate([ { none: ['message'] }, { success: [] }, { failedUp: ['cell'] }, { failedDown: ['cell'] } ]); const isOverlapping = (bridge, before, after) => { const beforeBounds = bridge.getRect(before); const afterBounds = bridge.getRect(after); return afterBounds.right > beforeBounds.left && afterBounds.left < beforeBounds.right; }; const isRow = elem => { return closest$1(elem, 'tr'); }; const verify = (bridge, before, beforeOffset, after, afterOffset, failure, isRoot) => { return closest$1(after, 'td,th', isRoot).bind(afterCell => { return closest$1(before, 'td,th', isRoot).map(beforeCell => { if (!eq$1(afterCell, beforeCell)) { return sharedOne(isRow, [ afterCell, beforeCell ]).fold(() => { return isOverlapping(bridge, beforeCell, afterCell) ? adt$2.success() : failure(beforeCell); }, _sharedRow => { return failure(beforeCell); }); } else { return eq$1(after, afterCell) && getEnd(afterCell) === afterOffset ? failure(beforeCell) : adt$2.none('in same cell'); } }); }).getOr(adt$2.none('default')); }; const cata = (subject, onNone, onSuccess, onFailedUp, onFailedDown) => { return subject.fold(onNone, onSuccess, onFailedUp, onFailedDown); }; const BeforeAfter = { ...adt$2, verify, cata }; const inParent = (parent, children, element, index) => ({ parent, children, element, index }); const indexInParent = element => parent(element).bind(parent => { const children = children$2(parent); return indexOf(children, element).map(index => inParent(parent, children, element, index)); }); const indexOf = (elements, element) => findIndex(elements, curry(eq$1, element)); const isBr = isTag('br'); const gatherer = (cand, gather, isRoot) => { return gather(cand, isRoot).bind(target => { return isText(target) && get$6(target).trim().length === 0 ? gatherer(target, gather, isRoot) : Optional.some(target); }); }; const handleBr = (isRoot, element, direction) => { return direction.traverse(element).orThunk(() => { return gatherer(element, direction.gather, isRoot); }).map(direction.relative); }; const findBr = (element, offset) => { return child$2(element, offset).filter(isBr).orThunk(() => { return child$2(element, offset - 1).filter(isBr); }); }; const handleParent = (isRoot, element, offset, direction) => { return findBr(element, offset).bind(br => { return direction.traverse(br).fold(() => { return gatherer(br, direction.gather, isRoot).map(direction.relative); }, adjacent => { return indexInParent(adjacent).map(info => { return Situ.on(info.parent, info.index); }); }); }); }; const tryBr = (isRoot, element, offset, direction) => { const target = isBr(element) ? handleBr(isRoot, element, direction) : handleParent(isRoot, element, offset, direction); return target.map(tgt => { return { start: tgt, finish: tgt }; }); }; const process = analysis => { return BeforeAfter.cata(analysis, _message => { return Optional.none(); }, () => { return Optional.none(); }, cell => { return Optional.some(point(cell, 0)); }, cell => { return Optional.some(point(cell, getEnd(cell))); }); }; const moveDown = (caret, amount) => { return { left: caret.left, top: caret.top + amount, right: caret.right, bottom: caret.bottom + amount }; }; const moveUp = (caret, amount) => { return { left: caret.left, top: caret.top - amount, right: caret.right, bottom: caret.bottom - amount }; }; const translate = (caret, xDelta, yDelta) => { return { left: caret.left + xDelta, top: caret.top + yDelta, right: caret.right + xDelta, bottom: caret.bottom + yDelta }; }; const getTop = caret => { return caret.top; }; const getBottom = caret => { return caret.bottom; }; const getPartialBox = (bridge, element, offset) => { if (offset >= 0 && offset < getEnd(element)) { return bridge.getRangedRect(element, offset, element, offset + 1); } else if (offset > 0) { return bridge.getRangedRect(element, offset - 1, element, offset); } return Optional.none(); }; const toCaret = rect => ({ left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }); const getElemBox = (bridge, element) => { return Optional.some(bridge.getRect(element)); }; const getBoxAt = (bridge, element, offset) => { if (isElement(element)) { return getElemBox(bridge, element).map(toCaret); } else if (isText(element)) { return getPartialBox(bridge, element, offset).map(toCaret); } else { return Optional.none(); } }; const getEntireBox = (bridge, element) => { if (isElement(element)) { return getElemBox(bridge, element).map(toCaret); } else if (isText(element)) { return bridge.getRangedRect(element, 0, element, getEnd(element)).map(toCaret); } else { return Optional.none(); } }; const JUMP_SIZE = 5; const NUM_RETRIES = 100; const adt$1 = Adt.generate([ { none: [] }, { retry: ['caret'] } ]); const isOutside = (caret, box) => { return caret.left < box.left || Math.abs(box.right - caret.left) < 1 || caret.left > box.right; }; const inOutsideBlock = (bridge, element, caret) => { return closest$2(element, isBlock).fold(never, cell => { return getEntireBox(bridge, cell).exists(box => { return isOutside(caret, box); }); }); }; const adjustDown = (bridge, element, guessBox, original, caret) => { const lowerCaret = moveDown(caret, JUMP_SIZE); if (Math.abs(guessBox.bottom - original.bottom) < 1) { return adt$1.retry(lowerCaret); } else if (guessBox.top > caret.bottom) { return adt$1.retry(lowerCaret); } else if (guessBox.top === caret.bottom) { return adt$1.retry(moveDown(caret, 1)); } else { return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(lowerCaret, JUMP_SIZE, 0)) : adt$1.none(); } }; const adjustUp = (bridge, element, guessBox, original, caret) => { const higherCaret = moveUp(caret, JUMP_SIZE); if (Math.abs(guessBox.top - original.top) < 1) { return adt$1.retry(higherCaret); } else if (guessBox.bottom < caret.top) { return adt$1.retry(higherCaret); } else if (guessBox.bottom === caret.top) { return adt$1.retry(moveUp(caret, 1)); } else { return inOutsideBlock(bridge, element, caret) ? adt$1.retry(translate(higherCaret, JUMP_SIZE, 0)) : adt$1.none(); } }; const upMovement = { point: getTop, adjuster: adjustUp, move: moveUp, gather: before }; const downMovement = { point: getBottom, adjuster: adjustDown, move: moveDown, gather: after$1 }; const isAtTable = (bridge, x, y) => { return bridge.elementFromPoint(x, y).filter(elm => { return name(elm) === 'table'; }).isSome(); }; const adjustForTable = (bridge, movement, original, caret, numRetries) => { return adjustTil(bridge, movement, original, movement.move(caret, JUMP_SIZE), numRetries); }; const adjustTil = (bridge, movement, original, caret, numRetries) => { if (numRetries === 0) { return Optional.some(caret); } if (isAtTable(bridge, caret.left, movement.point(caret))) { return adjustForTable(bridge, movement, original, caret, numRetries - 1); } return bridge.situsFromPoint(caret.left, movement.point(caret)).bind(guess => { return guess.start.fold(Optional.none, element => { return getEntireBox(bridge, element).bind(guessBox => { return movement.adjuster(bridge, element, guessBox, original, caret).fold(Optional.none, newCaret => { return adjustTil(bridge, movement, original, newCaret, numRetries - 1); }); }).orThunk(() => { return Optional.some(caret); }); }, Optional.none); }); }; const checkScroll = (movement, adjusted, bridge) => { if (movement.point(adjusted) > bridge.getInnerHeight()) { return Optional.some(movement.point(adjusted) - bridge.getInnerHeight()); } else if (movement.point(adjusted) < 0) { return Optional.some(-movement.point(adjusted)); } else { return Optional.none(); } }; const retry = (movement, bridge, caret) => { const moved = movement.move(caret, JUMP_SIZE); const adjusted = adjustTil(bridge, movement, caret, moved, NUM_RETRIES).getOr(moved); return checkScroll(movement, adjusted, bridge).fold(() => { return bridge.situsFromPoint(adjusted.left, movement.point(adjusted)); }, delta => { bridge.scrollBy(0, delta); return bridge.situsFromPoint(adjusted.left, movement.point(adjusted) - delta); }); }; const Retries = { tryUp: curry(retry, upMovement), tryDown: curry(retry, downMovement), getJumpSize: constant(JUMP_SIZE) }; const MAX_RETRIES = 20; const findSpot = (bridge, isRoot, direction) => { return bridge.getSelection().bind(sel => { return tryBr(isRoot, sel.finish, sel.foffset, direction).fold(() => { return Optional.some(point(sel.finish, sel.foffset)); }, brNeighbour => { const range = bridge.fromSitus(brNeighbour); const analysis = BeforeAfter.verify(bridge, sel.finish, sel.foffset, range.finish, range.foffset, direction.failure, isRoot); return process(analysis); }); }); }; const scan = (bridge, isRoot, element, offset, direction, numRetries) => { if (numRetries === 0) { return Optional.none(); } return tryCursor(bridge, isRoot, element, offset, direction).bind(situs => { const range = bridge.fromSitus(situs); const analysis = BeforeAfter.verify(bridge, element, offset, range.finish, range.foffset, direction.failure, isRoot); return BeforeAfter.cata(analysis, () => { return Optional.none(); }, () => { return Optional.some(situs); }, cell => { if (eq$1(element, cell) && offset === 0) { return tryAgain(bridge, element, offset, moveUp, direction); } else { return scan(bridge, isRoot, cell, 0, direction, numRetries - 1); } }, cell => { if (eq$1(element, cell) && offset === getEnd(cell)) { return tryAgain(bridge, element, offset, moveDown, direction); } else { return scan(bridge, isRoot, cell, getEnd(cell), direction, numRetries - 1); } }); }); }; const tryAgain = (bridge, element, offset, move, direction) => { return getBoxAt(bridge, element, offset).bind(box => { return tryAt(bridge, direction, move(box, Retries.getJumpSize())); }); }; const tryAt = (bridge, direction, box) => { const browser = detect$2().browser; if (browser.isChromium() || browser.isSafari() || browser.isFirefox()) { return direction.retry(bridge, box); } else { return Optional.none(); } }; const tryCursor = (bridge, isRoot, element, offset, direction) => { return getBoxAt(bridge, element, offset).bind(box => { return tryAt(bridge, direction, box); }); }; const handle$1 = (bridge, isRoot, direction) => { return findSpot(bridge, isRoot, direction).bind(spot => { return scan(bridge, isRoot, spot.element, spot.offset, direction, MAX_RETRIES).map(bridge.fromSitus); }); }; const inSameTable = (elem, table) => { return ancestor(elem, e => { return parent(e).exists(p => { return eq$1(p, table); }); }); }; const simulate = (bridge, isRoot, direction, initial, anchor) => { return closest$1(initial, 'td,th', isRoot).bind(start => { return closest$1(start, 'table', isRoot).bind(table => { if (!inSameTable(anchor, table)) { return Optional.none(); } return handle$1(bridge, isRoot, direction).bind(range => { return closest$1(range.finish, 'td,th', isRoot).map(finish => { return { start, finish, range }; }); }); }); }); }; const navigate = (bridge, isRoot, direction, initial, anchor, precheck) => { return precheck(initial, isRoot).orThunk(() => { return simulate(bridge, isRoot, direction, initial, anchor).map(info => { const range = info.range; return Response.create(Optional.some(makeSitus(range.start, range.soffset, range.finish, range.foffset)), true); }); }); }; const firstUpCheck = (initial, isRoot) => { return closest$1(initial, 'tr', isRoot).bind(startRow => { return closest$1(startRow, 'table', isRoot).bind(table => { const rows = descendants(table, 'tr'); if (eq$1(startRow, rows[0])) { return seekLeft(table, element => { return last$1(element).isSome(); }, isRoot).map(last => { const lastOffset = getEnd(last); return Response.create(Optional.some(makeSitus(last, lastOffset, last, lastOffset)), true); }); } else { return Optional.none(); } }); }); }; const lastDownCheck = (initial, isRoot) => { return closest$1(initial, 'tr', isRoot).bind(startRow => { return closest$1(startRow, 'table', isRoot).bind(table => { const rows = descendants(table, 'tr'); if (eq$1(startRow, rows[rows.length - 1])) { return seekRight(table, element => { return first(element).isSome(); }, isRoot).map(first => { return Response.create(Optional.some(makeSitus(first, 0, first, 0)), true); }); } else { return Optional.none(); } }); }); }; const select = (bridge, container, isRoot, direction, initial, anchor, selectRange) => { return simulate(bridge, isRoot, direction, initial, anchor).bind(info => { return detect(container, isRoot, info.start, info.finish, selectRange); }); }; const Cell = initial => { let value = initial; const get = () => { return value; }; const set = v => { value = v; }; return { get, set }; }; const singleton = doRevoke => { const subject = Cell(Optional.none()); const revoke = () => subject.get().each(doRevoke); const clear = () => { revoke(); subject.set(Optional.none()); }; const isSet = () => subject.get().isSome(); const get = () => subject.get(); const set = s => { revoke(); subject.set(Optional.some(s)); }; return { clear, isSet, get, set }; }; const value = () => { const subject = singleton(noop); const on = f => subject.get().each(f); return { ...subject, on }; }; const findCell = (target, isRoot) => closest$1(target, 'td,th', isRoot); const isInEditableContext = cell => parentElement(cell).exists(isEditable$1); const MouseSelection = (bridge, container, isRoot, annotations) => { const cursor = value(); const clearstate = cursor.clear; const applySelection = event => { cursor.on(start => { annotations.clearBeforeUpdate(container); findCell(event.target, isRoot).each(finish => { identify(start, finish, isRoot).each(cellSel => { const boxes = cellSel.boxes.getOr([]); if (boxes.length === 1) { const singleCell = boxes[0]; const isNonEditableCell = getRaw(singleCell) === 'false'; const isCellClosestContentEditable = is(closest(event.target), singleCell, eq$1); if (isNonEditableCell && isCellClosestContentEditable) { annotations.selectRange(container, boxes, singleCell, singleCell); } } else if (boxes.length > 1) { annotations.selectRange(container, boxes, cellSel.start, cellSel.finish); bridge.selectContents(finish); } }); }); }); }; const mousedown = event => { annotations.clear(container); findCell(event.target, isRoot).filter(isInEditableContext).each(cursor.set); }; const mouseover = event => { applySelection(event); }; const mouseup = event => { applySelection(event); clearstate(); }; return { clearstate, mousedown, mouseover, mouseup }; }; const down = { traverse: nextSibling, gather: after$1, relative: Situ.before, retry: Retries.tryDown, failure: BeforeAfter.failedDown }; const up = { traverse: prevSibling, gather: before, relative: Situ.before, retry: Retries.tryUp, failure: BeforeAfter.failedUp }; const isKey = key => { return keycode => { return keycode === key; }; }; const isUp = isKey(38); const isDown = isKey(40); const isNavigation = keycode => { return keycode >= 37 && keycode <= 40; }; const ltr = { isBackward: isKey(37), isForward: isKey(39) }; const rtl = { isBackward: isKey(39), isForward: isKey(37) }; const get$3 = _DOC => { const doc = _DOC !== undefined ? _DOC.dom : document; const x = doc.body.scrollLeft || doc.documentElement.scrollLeft; const y = doc.body.scrollTop || doc.documentElement.scrollTop; return SugarPosition(x, y); }; const by = (x, y, _DOC) => { const doc = _DOC !== undefined ? _DOC.dom : document; const win = doc.defaultView; if (win) { win.scrollBy(x, y); } }; const adt = Adt.generate([ { domRange: ['rng'] }, { relative: [ 'startSitu', 'finishSitu' ] }, { exact: [ 'start', 'soffset', 'finish', 'foffset' ] } ]); const exactFromRange = simRange => adt.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset); const getStart = selection => selection.match({ domRange: rng => SugarElement.fromDom(rng.startContainer), relative: (startSitu, _finishSitu) => Situ.getStart(startSitu), exact: (start, _soffset, _finish, _foffset) => start }); const domRange = adt.domRange; const relative = adt.relative; const exact = adt.exact; const getWin = selection => { const start = getStart(selection); return defaultView(start); }; const range = SimRange.create; const SimSelection = { domRange, relative, exact, exactFromRange, getWin, range }; const caretPositionFromPoint = (doc, x, y) => { var _a; return Optional.from((_a = doc.caretPositionFromPoint) === null || _a === void 0 ? void 0 : _a.call(doc, x, y)).bind(pos => { if (pos.offsetNode === null) { return Optional.none(); } const r = doc.createRange(); r.setStart(pos.offsetNode, pos.offset); r.collapse(); return Optional.some(r); }); }; const caretRangeFromPoint = (doc, x, y) => { var _a; return Optional.from((_a = doc.caretRangeFromPoint) === null || _a === void 0 ? void 0 : _a.call(doc, x, y)); }; const availableSearch = (doc, x, y) => { if (doc.caretPositionFromPoint) { return caretPositionFromPoint(doc, x, y); } else if (doc.caretRangeFromPoint) { return caretRangeFromPoint(doc, x, y); } else { return Optional.none(); } }; const fromPoint = (win, x, y) => { const doc = win.document; return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset)); }; const beforeSpecial = (element, offset) => { const name$1 = name(element); if ('input' === name$1) { return Situ.after(element); } else if (!contains$2([ 'br', 'img' ], name$1)) { return Situ.on(element, offset); } else { return offset === 0 ? Situ.before(element) : Situ.after(element); } }; const preprocessRelative = (startSitu, finishSitu) => { const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after); const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after); return SimSelection.relative(start, finish); }; const preprocessExact = (start, soffset, finish, foffset) => { const startSitu = beforeSpecial(start, soffset); const finishSitu = beforeSpecial(finish, foffset); return SimSelection.relative(startSitu, finishSitu); }; const makeRange = (start, soffset, finish, foffset) => { const doc = owner(start); const rng = doc.dom.createRange(); rng.setStart(start.dom, soffset); rng.setEnd(finish.dom, foffset); return rng; }; const after = (start, soffset, finish, foffset) => { const r = makeRange(start, soffset, finish, foffset); const same = eq$1(start, finish) && soffset === foffset; return r.collapsed && !same; }; const getNativeSelection = win => Optional.from(win.getSelection()); const doSetNativeRange = (win, rng) => { getNativeSelection(win).each(selection => { selection.removeAllRanges(); selection.addRange(rng); }); }; const doSetRange = (win, start, soffset, finish, foffset) => { const rng = exactToNative(win, start, soffset, finish, foffset); doSetNativeRange(win, rng); }; const setLegacyRtlRange = (win, selection, start, soffset, finish, foffset) => { selection.collapse(start.dom, soffset); selection.extend(finish.dom, foffset); }; const setRangeFromRelative = (win, relative) => diagnose(win, relative).match({ ltr: (start, soffset, finish, foffset) => { doSetRange(win, start, soffset, finish, foffset); }, rtl: (start, soffset, finish, foffset) => { getNativeSelection(win).each(selection => { if (selection.setBaseAndExtent) { selection.setBaseAndExtent(start.dom, soffset, finish.dom, foffset); } else if (selection.extend) { try { setLegacyRtlRange(win, selection, start, soffset, finish, foffset); } catch (_a) { doSetRange(win, finish, foffset, start, soffset); } } else { doSetRange(win, finish, foffset, start, soffset); } }); } }); const setExact = (win, start, soffset, finish, foffset) => { const relative = preprocessExact(start, soffset, finish, foffset); setRangeFromRelative(win, relative); }; const setRelative = (win, startSitu, finishSitu) => { const relative = preprocessRelative(startSitu, finishSitu); setRangeFromRelative(win, relative); }; const readRange = selection => { if (selection.rangeCount > 0) { const firstRng = selection.getRangeAt(0); const lastRng = selection.getRangeAt(selection.rangeCount - 1); return Optional.some(SimRange.create(SugarElement.fromDom(firstRng.startContainer), firstRng.startOffset, SugarElement.fromDom(lastRng.endContainer), lastRng.endOffset)); } else { return Optional.none(); } }; const doGetExact = selection => { if (selection.anchorNode === null || selection.focusNode === null) { return readRange(selection); } else { const anchor = SugarElement.fromDom(selection.anchorNode); const focus = SugarElement.fromDom(selection.focusNode); return after(anchor, selection.anchorOffset, focus, selection.focusOffset) ? Optional.some(SimRange.create(anchor, selection.anchorOffset, focus, selection.focusOffset)) : readRange(selection); } }; const setToElement = (win, element, selectNodeContents$1 = true) => { const rngGetter = selectNodeContents$1 ? selectNodeContents : selectNode; const rng = rngGetter(win, element); doSetNativeRange(win, rng); }; const getExact = win => getNativeSelection(win).filter(sel => sel.rangeCount > 0).bind(doGetExact); const get$2 = win => getExact(win).map(range => SimSelection.exact(range.start, range.soffset, range.finish, range.foffset)); const getFirstRect = (win, selection) => { const rng = asLtrRange(win, selection); return getFirstRect$1(rng); }; const getAtPoint = (win, x, y) => fromPoint(win, x, y); const clear = win => { getNativeSelection(win).each(selection => selection.removeAllRanges()); }; const WindowBridge = win => { const elementFromPoint = (x, y) => { return SugarElement.fromPoint(SugarElement.fromDom(win.document), x, y); }; const getRect = element => { return element.dom.getBoundingClientRect(); }; const getRangedRect = (start, soffset, finish, foffset) => { const sel = SimSelection.exact(start, soffset, finish, foffset); return getFirstRect(win, sel); }; const getSelection = () => { return get$2(win).map(exactAdt => { return convertToRange(win, exactAdt); }); }; const fromSitus = situs => { const relative = SimSelection.relative(situs.start, situs.finish); return convertToRange(win, relative); }; const situsFromPoint = (x, y) => { return getAtPoint(win, x, y).map(exact => { return Situs.create(exact.start, exact.soffset, exact.finish, exact.foffset); }); }; const clearSelection = () => { clear(win); }; const collapseSelection = (toStart = false) => { get$2(win).each(sel => sel.fold(rng => rng.collapse(toStart), (startSitu, finishSitu) => { const situ = toStart ? startSitu : finishSitu; setRelative(win, situ, situ); }, (start, soffset, finish, foffset) => { const node = toStart ? start : finish; const offset = toStart ? soffset : foffset; setExact(win, node, offset, node, offset); })); }; const selectNode = element => { setToElement(win, element, false); }; const selectContents = element => { setToElement(win, element); }; const setSelection = sel => { setExact(win, sel.start, sel.soffset, sel.finish, sel.foffset); }; const setRelativeSelection = (start, finish) => { setRelative(win, start, finish); }; const getInnerHeight = () => { return win.innerHeight; }; const getScrollY = () => { const pos = get$3(SugarElement.fromDom(win.document)); return pos.top; }; const scrollBy = (x, y) => { by(x, y, SugarElement.fromDom(win.document)); }; return { elementFromPoint, getRect, getRangedRect, getSelection, fromSitus, situsFromPoint, clearSelection, collapseSelection, setSelection, setRelativeSelection, selectNode, selectContents, getInnerHeight, getScrollY, scrollBy }; }; const rc = (rows, cols) => ({ rows, cols }); const mouse = (win, container, isRoot, annotations) => { const bridge = WindowBridge(win); const handlers = MouseSelection(bridge, container, isRoot, annotations); return { clearstate: handlers.clearstate, mousedown: handlers.mousedown, mouseover: handlers.mouseover, mouseup: handlers.mouseup }; }; const isEditableNode = node => closest$2(node, isHTMLElement).exists(isEditable$1); const isEditableSelection = (start, finish) => isEditableNode(start) || isEditableNode(finish); const keyboard = (win, container, isRoot, annotations) => { const bridge = WindowBridge(win); const clearToNavigate = () => { annotations.clear(container); return Optional.none(); }; const keydown = (event, start, soffset, finish, foffset, direction) => { const realEvent = event.raw; const keycode = realEvent.which; const shiftKey = realEvent.shiftKey === true; const handler = retrieve$1(container, annotations.selectedSelector).fold(() => { if (isNavigation(keycode) && !shiftKey) { annotations.clearBeforeUpdate(container); } if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) { return Optional.none; } else if (isDown(keycode) && shiftKey) { return curry(select, bridge, container, isRoot, down, finish, start, annotations.selectRange); } else if (isUp(keycode) && shiftKey) { return curry(select, bridge, container, isRoot, up, finish, start, annotations.selectRange); } else if (isDown(keycode)) { return curry(navigate, bridge, isRoot, down, finish, start, lastDownCheck); } else if (isUp(keycode)) { return curry(navigate, bridge, isRoot, up, finish, start, firstUpCheck); } else { return Optional.none; } }, selected => { const update$1 = attempts => { return () => { const navigation = findMap(attempts, delta => { return update(delta.rows, delta.cols, container, selected, annotations); }); return navigation.fold(() => { return getEdges(container, annotations.firstSelectedSelector, annotations.lastSelectedSelector).map(edges => { const relative = isDown(keycode) || direction.isForward(keycode) ? Situ.after : Situ.before; bridge.setRelativeSelection(Situ.on(edges.first, 0), relative(edges.table)); annotations.clear(container); return Response.create(Optional.none(), true); }); }, _ => { return Optional.some(Response.create(Optional.none(), true)); }); }; }; if (isNavigation(keycode) && shiftKey && !isEditableSelection(start, finish)) { return Optional.none; } else if (isDown(keycode) && shiftKey) { return update$1([rc(+1, 0)]); } else if (isUp(keycode) && shiftKey) { return update$1([rc(-1, 0)]); } else if (direction.isBackward(keycode) && shiftKey) { return update$1([ rc(0, -1), rc(-1, 0) ]); } else if (direction.isForward(keycode) && shiftKey) { return update$1([ rc(0, +1), rc(+1, 0) ]); } else if (isNavigation(keycode) && !shiftKey) { return clearToNavigate; } else { return Optional.none; } }); return handler(); }; const keyup = (event, start, soffset, finish, foffset) => { return retrieve$1(container, annotations.selectedSelector).fold(() => { const realEvent = event.raw; const keycode = realEvent.which; const shiftKey = realEvent.shiftKey === true; if (!shiftKey) { return Optional.none(); } if (isNavigation(keycode) && isEditableSelection(start, finish)) { return sync(container, isRoot, start, soffset, finish, foffset, annotations.selectRange); } else { return Optional.none(); } }, Optional.none); }; return { keydown, keyup }; }; const external = (win, container, isRoot, annotations) => { const bridge = WindowBridge(win); return (start, finish) => { annotations.clearBeforeUpdate(container); identify(start, finish, isRoot).each(cellSel => { const boxes = cellSel.boxes.getOr([]); annotations.selectRange(container, boxes, cellSel.start, cellSel.finish); bridge.selectContents(finish); bridge.collapseSelection(); }); }; }; const read = (element, attr) => { const value = get$b(element, attr); return value === undefined || value === '' ? [] : value.split(' '); }; const add$2 = (element, attr, id) => { const old = read(element, attr); const nu = old.concat([id]); set$2(element, attr, nu.join(' ')); return true; }; const remove$4 = (element, attr, id) => { const nu = filter$2(read(element, attr), v => v !== id); if (nu.length > 0) { set$2(element, attr, nu.join(' ')); } else { remove$7(element, attr); } return false; }; const supports = element => element.dom.classList !== undefined; const get$1 = element => read(element, 'class'); const add$1 = (element, clazz) => add$2(element, 'class', clazz); const remove$3 = (element, clazz) => remove$4(element, 'class', clazz); const add = (element, clazz) => { if (supports(element)) { element.dom.classList.add(clazz); } else { add$1(element, clazz); } }; const cleanClass = element => { const classList = supports(element) ? element.dom.classList : get$1(element); if (classList.length === 0) { remove$7(element, 'class'); } }; const remove$2 = (element, clazz) => { if (supports(element)) { const classList = element.dom.classList; classList.remove(clazz); } else { remove$3(element, clazz); } cleanClass(element); }; const has = (element, clazz) => supports(element) && element.dom.classList.contains(clazz); const remove$1 = (element, classes) => { each$2(classes, x => { remove$2(element, x); }); }; const addClass = clazz => element => { add(element, clazz); }; const removeClasses = classes => element => { remove$1(element, classes); }; const byClass = ephemera => { const addSelectionClass = addClass(ephemera.selected); const removeSelectionClasses = removeClasses([ ephemera.selected, ephemera.lastSelected, ephemera.firstSelected ]); const clear = container => { const sels = descendants(container, ephemera.selectedSelector); each$2(sels, removeSelectionClasses); }; const selectRange = (container, cells, start, finish) => { clear(container); each$2(cells, addSelectionClass); add(start, ephemera.firstSelected); add(finish, ephemera.lastSelected); }; return { clearBeforeUpdate: clear, clear, selectRange, selectedSelector: ephemera.selectedSelector, firstSelectedSelector: ephemera.firstSelectedSelector, lastSelectedSelector: ephemera.lastSelectedSelector }; }; const byAttr = (ephemera, onSelection, onClear) => { const removeSelectionAttributes = element => { remove$7(element, ephemera.selected); remove$7(element, ephemera.firstSelected); remove$7(element, ephemera.lastSelected); }; const addSelectionAttribute = element => { set$2(element, ephemera.selected, '1'); }; const clear = container => { clearBeforeUpdate(container); onClear(); }; const clearBeforeUpdate = container => { const sels = descendants(container, `${ ephemera.selectedSelector },${ ephemera.firstSelectedSelector },${ ephemera.lastSelectedSelector }`); each$2(sels, removeSelectionAttributes); }; const selectRange = (container, cells, start, finish) => { clear(container); each$2(cells, addSelectionAttribute); set$2(start, ephemera.firstSelected, '1'); set$2(finish, ephemera.lastSelected, '1'); onSelection(cells, start, finish); }; return { clearBeforeUpdate, clear, selectRange, selectedSelector: ephemera.selectedSelector, firstSelectedSelector: ephemera.firstSelectedSelector, lastSelectedSelector: ephemera.lastSelectedSelector }; }; const SelectionAnnotation = { byClass, byAttr }; const fold = (subject, onNone, onMultiple, onSingle) => { switch (subject.tag) { case 'none': return onNone(); case 'single': return onSingle(subject.element); case 'multiple': return onMultiple(subject.elements); } }; const none = () => ({ tag: 'none' }); const multiple = elements => ({ tag: 'multiple', elements }); const single = element => ({ tag: 'single', element }); const Selections = (lazyRoot, getStart, selectedSelector) => { const get = () => retrieve(lazyRoot(), selectedSelector).fold(() => getStart().fold(none, single), multiple); return { get }; }; const getUpOrLeftCells = (grid, selectedCells) => { const upGrid = grid.slice(0, selectedCells[selectedCells.length - 1].row + 1); const upDetails = toDetailList(upGrid); return bind$2(upDetails, detail => { const slicedCells = detail.cells.slice(0, selectedCells[selectedCells.length - 1].column + 1); return map$1(slicedCells, cell => cell.element); }); }; const getDownOrRightCells = (grid, selectedCells) => { const downGrid = grid.slice(selectedCells[0].row + selectedCells[0].rowspan - 1, grid.length); const downDetails = toDetailList(downGrid); return bind$2(downDetails, detail => { const slicedCells = detail.cells.slice(selectedCells[0].column + selectedCells[0].colspan - 1, detail.cells.length); return map$1(slicedCells, cell => cell.element); }); }; const getOtherCells = (table, target, generators) => { const warehouse = Warehouse.fromTable(table); const details = onCells(warehouse, target); return details.map(selectedCells => { const grid = toGrid(warehouse, generators, false); const {rows} = extractGridDetails(grid); const upOrLeftCells = getUpOrLeftCells(rows, selectedCells); const downOrRightCells = getDownOrRightCells(rows, selectedCells); return { upOrLeftCells, downOrRightCells }; }); }; const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({ target, x, y, stop, prevent, kill, raw }); const fromRawEvent$1 = rawEvent => { const target = SugarElement.fromDom(getOriginalEventTarget(rawEvent).getOr(rawEvent.target)); const stop = () => rawEvent.stopPropagation(); const prevent = () => rawEvent.preventDefault(); const kill = compose(prevent, stop); return mkEvent(target, rawEvent.clientX, rawEvent.clientY, stop, prevent, kill, rawEvent); }; const handle = (filter, handler) => rawEvent => { if (filter(rawEvent)) { handler(fromRawEvent$1(rawEvent)); } }; const binder = (element, event, filter, handler, useCapture) => { const wrapped = handle(filter, handler); element.dom.addEventListener(event, wrapped, useCapture); return { unbind: curry(unbind, element, event, wrapped, useCapture) }; }; const bind$1 = (element, event, filter, handler) => binder(element, event, filter, handler, false); const unbind = (element, event, handler, useCapture) => { element.dom.removeEventListener(event, handler, useCapture); }; const filter = always; const bind = (element, event, handler) => bind$1(element, event, filter, handler); const fromRawEvent = fromRawEvent$1; const hasInternalTarget = e => !has(SugarElement.fromDom(e.target), 'ephox-snooker-resizer-bar'); const TableCellSelectionHandler = (editor, resizeHandler) => { const cellSelection = Selections(() => SugarElement.fromDom(editor.getBody()), () => getSelectionCell(getSelectionStart(editor), getIsRoot(editor)), ephemera.selectedSelector); const onSelection = (cells, start, finish) => { const tableOpt = table(start); tableOpt.each(table => { const cellsDom = map$1(cells, cell => cell.dom); const cloneFormats = getTableCloneElements(editor); const generators = cellOperations(noop, SugarElement.fromDom(editor.getDoc()), cloneFormats); const selectedCells = getCellsFromSelection(editor); const otherCellsDom = getOtherCells(table, { selection: selectedCells }, generators).map(otherCells => map(otherCells, cellArr => map$1(cellArr, cell => cell.dom))).getOrUndefined(); fireTableSelectionChange(editor, cellsDom, start.dom, finish.dom, otherCellsDom); }); }; const onClear = () => fireTableSelectionClear(editor); const annotations = SelectionAnnotation.byAttr(ephemera, onSelection, onClear); editor.on('init', _e => { const win = editor.getWin(); const body = getBody(editor); const isRoot = getIsRoot(editor); const syncSelection = () => { const sel = editor.selection; const start = SugarElement.fromDom(sel.getStart()); const end = SugarElement.fromDom(sel.getEnd()); const shared = sharedOne(table, [ start, end ]); shared.fold(() => annotations.clear(body), noop); }; const mouseHandlers = mouse(win, body, isRoot, annotations); const keyHandlers = keyboard(win, body, isRoot, annotations); const external$1 = external(win, body, isRoot, annotations); const hasShiftKey = event => event.raw.shiftKey === true; editor.on('TableSelectorChange', e => external$1(e.start, e.finish)); const handleResponse = (event, response) => { if (!hasShiftKey(event)) { return; } if (response.kill) { event.kill(); } response.selection.each(ns => { const relative = SimSelection.relative(ns.start, ns.finish); const rng = asLtrRange(win, relative); editor.selection.setRng(rng); }); }; const keyup = event => { const wrappedEvent = fromRawEvent(event); if (wrappedEvent.raw.shiftKey && isNavigation(wrappedEvent.raw.which)) { const rng = editor.selection.getRng(); const start = SugarElement.fromDom(rng.startContainer); const end = SugarElement.fromDom(rng.endContainer); keyHandlers.keyup(wrappedEvent, start, rng.startOffset, end, rng.endOffset).each(response => { handleResponse(wrappedEvent, response); }); } }; const keydown = event => { const wrappedEvent = fromRawEvent(event); resizeHandler.hide(); const rng = editor.selection.getRng(); const start = SugarElement.fromDom(rng.startContainer); const end = SugarElement.fromDom(rng.endContainer); const direction = onDirection(ltr, rtl)(SugarElement.fromDom(editor.selection.getStart())); keyHandlers.keydown(wrappedEvent, start, rng.startOffset, end, rng.endOffset, direction).each(response => { handleResponse(wrappedEvent, response); }); resizeHandler.show(); }; const isLeftMouse = raw => raw.button === 0; const isLeftButtonPressed = raw => { if (raw.buttons === undefined) { return true; } return (raw.buttons & 1) !== 0; }; const dragStart = _e => { mouseHandlers.clearstate(); }; const mouseDown = e => { if (isLeftMouse(e) && hasInternalTarget(e)) { mouseHandlers.mousedown(fromRawEvent(e)); } }; const mouseOver = e => { if (isLeftButtonPressed(e) && hasInternalTarget(e)) { mouseHandlers.mouseover(fromRawEvent(e)); } }; const mouseUp = e => { if (isLeftMouse(e) && hasInternalTarget(e)) { mouseHandlers.mouseup(fromRawEvent(e)); } }; const getDoubleTap = () => { const lastTarget = Cell(SugarElement.fromDom(body)); const lastTimeStamp = Cell(0); const touchEnd = t => { const target = SugarElement.fromDom(t.target); if (isTag('td')(target) || isTag('th')(target)) { const lT = lastTarget.get(); const lTS = lastTimeStamp.get(); if (eq$1(lT, target) && t.timeStamp - lTS < 300) { t.preventDefault(); external$1(target, target); } } lastTarget.set(target); lastTimeStamp.set(t.timeStamp); }; return { touchEnd }; }; const doubleTap = getDoubleTap(); editor.on('dragstart', dragStart); editor.on('mousedown', mouseDown); editor.on('mouseover', mouseOver); editor.on('mouseup', mouseUp); editor.on('touchend', doubleTap.touchEnd); editor.on('keyup', keyup); editor.on('keydown', keydown); editor.on('NodeChange', syncSelection); }); editor.on('PreInit', () => { editor.serializer.addTempAttr(ephemera.firstSelected); editor.serializer.addTempAttr(ephemera.lastSelected); }); const clearSelectedCells = container => annotations.clear(SugarElement.fromDom(container)); const getSelectedCells = () => fold(cellSelection.get(), constant([]), cells => { return map$1(cells, cell => cell.dom); }, cell => [cell.dom]); return { getSelectedCells, clearSelectedCells }; }; const Event = fields => { let handlers = []; const bind = handler => { if (handler === undefined) { throw new Error('Event bind error: undefined handler'); } handlers.push(handler); }; const unbind = handler => { handlers = filter$2(handlers, h => { return h !== handler; }); }; const trigger = (...args) => { const event = {}; each$2(fields, (name, i) => { event[name] = args[i]; }); each$2(handlers, handler => { handler(event); }); }; return { bind, unbind, trigger }; }; const create$1 = typeDefs => { const registry = map(typeDefs, event => { return { bind: event.bind, unbind: event.unbind }; }); const trigger = map(typeDefs, event => { return event.trigger; }); return { registry, trigger }; }; const last = (fn, rate) => { let timer = null; const cancel = () => { if (!isNull(timer)) { clearTimeout(timer); timer = null; } }; const throttle = (...args) => { cancel(); timer = setTimeout(() => { timer = null; fn.apply(null, args); }, rate); }; return { cancel, throttle }; }; const sort = arr => { return arr.slice(0).sort(); }; const reqMessage = (required, keys) => { throw new Error('All required keys (' + sort(required).join(', ') + ') were not specified. Specified keys were: ' + sort(keys).join(', ') + '.'); }; const unsuppMessage = unsupported => { throw new Error('Unsupported keys for object: ' + sort(unsupported).join(', ')); }; const validateStrArr = (label, array) => { if (!isArray(array)) { throw new Error('The ' + label + ' fields must be an array. Was: ' + array + '.'); } each$2(array, a => { if (!isString(a)) { throw new Error('The value ' + a + ' in the ' + label + ' fields was not a string.'); } }); }; const invalidTypeMessage = (incorrect, type) => { throw new Error('All values need to be of type: ' + type + '. Keys (' + sort(incorrect).join(', ') + ') were not.'); }; const checkDupes = everything => { const sorted = sort(everything); const dupe = find$1(sorted, (s, i) => { return i < sorted.length - 1 && s === sorted[i + 1]; }); dupe.each(d => { throw new Error('The field: ' + d + ' occurs more than once in the combined fields: [' + sorted.join(', ') + '].'); }); }; const base = (handleUnsupported, required) => { return baseWith(handleUnsupported, required, { validate: isFunction, label: 'function' }); }; const baseWith = (handleUnsupported, required, pred) => { if (required.length === 0) { throw new Error('You must specify at least one required field.'); } validateStrArr('required', required); checkDupes(required); return obj => { const keys$1 = keys(obj); const allReqd = forall(required, req => { return contains$2(keys$1, req); }); if (!allReqd) { reqMessage(required, keys$1); } handleUnsupported(required, keys$1); const invalidKeys = filter$2(required, key => { return !pred.validate(obj[key], key); }); if (invalidKeys.length > 0) { invalidTypeMessage(invalidKeys, pred.label); } return obj; }; }; const handleExact = (required, keys) => { const unsupported = filter$2(keys, key => { return !contains$2(required, key); }); if (unsupported.length > 0) { unsuppMessage(unsupported); } }; const exactly = required => base(handleExact, required); const DragMode = exactly([ 'compare', 'extract', 'mutate', 'sink' ]); const DragSink = exactly([ 'element', 'start', 'stop', 'destroy' ]); const DragApi = exactly([ 'forceDrop', 'drop', 'move', 'delayDrop' ]); const InDrag = () => { let previous = Optional.none(); const reset = () => { previous = Optional.none(); }; const update = (mode, nu) => { const result = previous.map(old => { return mode.compare(old, nu); }); previous = Optional.some(nu); return result; }; const onEvent = (event, mode) => { const dataOption = mode.extract(event); dataOption.each(data => { const offset = update(mode, data); offset.each(d => { events.trigger.move(d); }); }); }; const events = create$1({ move: Event(['info']) }); return { onEvent, reset, events: events.registry }; }; const NoDrag = () => { const events = create$1({ move: Event(['info']) }); return { onEvent: noop, reset: noop, events: events.registry }; }; const Movement = () => { const noDragState = NoDrag(); const inDragState = InDrag(); let dragState = noDragState; const on = () => { dragState.reset(); dragState = inDragState; }; const off = () => { dragState.reset(); dragState = noDragState; }; const onEvent = (event, mode) => { dragState.onEvent(event, mode); }; const isOn = () => { return dragState === inDragState; }; return { on, off, isOn, onEvent, events: inDragState.events }; }; const setup = (mutation, mode, settings) => { let active = false; const events = create$1({ start: Event([]), stop: Event([]) }); const movement = Movement(); const drop = () => { sink.stop(); if (movement.isOn()) { movement.off(); events.trigger.stop(); } }; const throttledDrop = last(drop, 200); const go = parent => { sink.start(parent); movement.on(); events.trigger.start(); }; const mousemove = event => { throttledDrop.cancel(); movement.onEvent(event, mode); }; movement.events.move.bind(event => { mode.mutate(mutation, event.info); }); const on = () => { active = true; }; const off = () => { active = false; }; const isActive = () => active; const runIfActive = f => { return (...args) => { if (active) { f.apply(null, args); } }; }; const sink = mode.sink(DragApi({ forceDrop: drop, drop: runIfActive(drop), move: runIfActive(mousemove), delayDrop: runIfActive(throttledDrop.throttle) }), settings); const destroy = () => { sink.destroy(); }; return { element: sink.element, go, on, off, isActive, destroy, events: events.registry }; }; const css = namespace => { const dashNamespace = namespace.replace(/\./g, '-'); const resolve = str => { return dashNamespace + '-' + str; }; return { resolve }; }; const styles$1 = css('ephox-dragster'); const resolve$1 = styles$1.resolve; const Blocker = options => { const settings = { layerClass: resolve$1('blocker'), ...options }; const div = SugarElement.fromTag('div'); set$2(div, 'role', 'presentation'); setAll(div, { position: 'fixed', left: '0px', top: '0px', width: '100%', height: '100%' }); add(div, resolve$1('blocker')); add(div, settings.layerClass); const element = constant(div); const destroy = () => { remove$6(div); }; return { element, destroy }; }; const compare = (old, nu) => { return SugarPosition(nu.left - old.left, nu.top - old.top); }; const extract = event => { return Optional.some(SugarPosition(event.x, event.y)); }; const mutate = (mutation, info) => { mutation.mutate(info.left, info.top); }; const sink = (dragApi, settings) => { const blocker = Blocker(settings); const mdown = bind(blocker.element(), 'mousedown', dragApi.forceDrop); const mup = bind(blocker.element(), 'mouseup', dragApi.drop); const mmove = bind(blocker.element(), 'mousemove', dragApi.move); const mout = bind(blocker.element(), 'mouseout', dragApi.delayDrop); const destroy = () => { blocker.destroy(); mup.unbind(); mmove.unbind(); mout.unbind(); mdown.unbind(); }; const start = parent => { append$1(parent, blocker.element()); }; const stop = () => { remove$6(blocker.element()); }; return DragSink({ element: blocker.element, start, stop, destroy }); }; var MouseDrag = DragMode({ compare, extract, sink, mutate }); const transform = (mutation, settings = {}) => { var _a; const mode = (_a = settings.mode) !== null && _a !== void 0 ? _a : MouseDrag; return setup(mutation, mode, settings); }; const styles = css('ephox-snooker'); const resolve = styles.resolve; const Mutation = () => { const events = create$1({ drag: Event([ 'xDelta', 'yDelta' ]) }); const mutate = (x, y) => { events.trigger.drag(x, y); }; return { mutate, events: events.registry }; }; const BarMutation = () => { const events = create$1({ drag: Event([ 'xDelta', 'yDelta', 'target' ]) }); let target = Optional.none(); const delegate = Mutation(); delegate.events.drag.bind(event => { target.each(t => { events.trigger.drag(event.xDelta, event.yDelta, t); }); }); const assign = t => { target = Optional.some(t); }; const get = () => { return target; }; return { assign, get, mutate: delegate.mutate, events: events.registry }; }; const col = (column, x, y, w, h) => { const bar = SugarElement.fromTag('div'); setAll(bar, { position: 'absolute', left: x - w / 2 + 'px', top: y + 'px', height: h + 'px', width: w + 'px' }); setAll$1(bar, { 'data-column': column, 'role': 'presentation' }); return bar; }; const row = (r, x, y, w, h) => { const bar = SugarElement.fromTag('div'); setAll(bar, { position: 'absolute', left: x + 'px', top: y - h / 2 + 'px', height: h + 'px', width: w + 'px' }); setAll$1(bar, { 'data-row': r, 'role': 'presentation' }); return bar; }; const resizeBar = resolve('resizer-bar'); const resizeRowBar = resolve('resizer-rows'); const resizeColBar = resolve('resizer-cols'); const BAR_THICKNESS = 7; const resizableRows = (warehouse, isResizable) => bind$2(warehouse.all, (row, i) => isResizable(row.element) ? [i] : []); const resizableColumns = (warehouse, isResizable) => { const resizableCols = []; range$1(warehouse.grid.columns, index => { const colElmOpt = Warehouse.getColumnAt(warehouse, index).map(col => col.element); if (colElmOpt.forall(isResizable)) { resizableCols.push(index); } }); return filter$2(resizableCols, colIndex => { const columnCells = Warehouse.filterItems(warehouse, cell => cell.column === colIndex); return forall(columnCells, cell => isResizable(cell.element)); }); }; const destroy = wire => { const previous = descendants(wire.parent(), '.' + resizeBar); each$2(previous, remove$6); }; const drawBar = (wire, positions, create) => { const origin = wire.origin(); each$2(positions, cpOption => { cpOption.each(cp => { const bar = create(origin, cp); add(bar, resizeBar); append$1(wire.parent(), bar); }); }); }; const refreshCol = (wire, colPositions, position, tableHeight) => { drawBar(wire, colPositions, (origin, cp) => { const colBar = col(cp.col, cp.x - origin.left, position.top - origin.top, BAR_THICKNESS, tableHeight); add(colBar, resizeColBar); return colBar; }); }; const refreshRow = (wire, rowPositions, position, tableWidth) => { drawBar(wire, rowPositions, (origin, cp) => { const rowBar = row(cp.row, position.left - origin.left, cp.y - origin.top, tableWidth, BAR_THICKNESS); add(rowBar, resizeRowBar); return rowBar; }); }; const refreshGrid = (warhouse, wire, table, rows, cols) => { const position = absolute(table); const isResizable = wire.isResizable; const rowPositions = rows.length > 0 ? height.positions(rows, table) : []; const resizableRowBars = rowPositions.length > 0 ? resizableRows(warhouse, isResizable) : []; const resizableRowPositions = filter$2(rowPositions, (_pos, i) => exists(resizableRowBars, barIndex => i === barIndex)); refreshRow(wire, resizableRowPositions, position, getOuter$2(table)); const colPositions = cols.length > 0 ? width.positions(cols, table) : []; const resizableColBars = colPositions.length > 0 ? resizableColumns(warhouse, isResizable) : []; const resizableColPositions = filter$2(colPositions, (_pos, i) => exists(resizableColBars, barIndex => i === barIndex)); refreshCol(wire, resizableColPositions, position, getOuter$1(table)); }; const refresh = (wire, table) => { destroy(wire); if (wire.isResizable(table)) { const warehouse = Warehouse.fromTable(table); const rows$1 = rows(warehouse); const cols = columns(warehouse); refreshGrid(warehouse, wire, table, rows$1, cols); } }; const each = (wire, f) => { const bars = descendants(wire.parent(), '.' + resizeBar); each$2(bars, f); }; const hide = wire => { each(wire, bar => { set$1(bar, 'display', 'none'); }); }; const show = wire => { each(wire, bar => { set$1(bar, 'display', 'block'); }); }; const isRowBar = element => { return has(element, resizeRowBar); }; const isColBar = element => { return has(element, resizeColBar); }; const resizeBarDragging = resolve('resizer-bar-dragging'); const BarManager = wire => { const mutation = BarMutation(); const resizing = transform(mutation, {}); let hoverTable = Optional.none(); const getResizer = (element, type) => { return Optional.from(get$b(element, type)); }; mutation.events.drag.bind(event => { getResizer(event.target, 'data-row').each(_dataRow => { const currentRow = getCssValue(event.target, 'top'); set$1(event.target, 'top', currentRow + event.yDelta + 'px'); }); getResizer(event.target, 'data-column').each(_dataCol => { const currentCol = getCssValue(event.target, 'left'); set$1(event.target, 'left', currentCol + event.xDelta + 'px'); }); }); const getDelta = (target, dir) => { const newX = getCssValue(target, dir); const oldX = getAttrValue(target, 'data-initial-' + dir, 0); return newX - oldX; }; resizing.events.stop.bind(() => { mutation.get().each(target => { hoverTable.each(table => { getResizer(target, 'data-row').each(row => { const delta = getDelta(target, 'top'); remove$7(target, 'data-initial-top'); events.trigger.adjustHeight(table, delta, parseInt(row, 10)); }); getResizer(target, 'data-column').each(column => { const delta = getDelta(target, 'left'); remove$7(target, 'data-initial-left'); events.trigger.adjustWidth(table, delta, parseInt(column, 10)); }); refresh(wire, table); }); }); }); const handler = (target, dir) => { events.trigger.startAdjust(); mutation.assign(target); set$2(target, 'data-initial-' + dir, getCssValue(target, dir)); add(target, resizeBarDragging); set$1(target, 'opacity', '0.2'); resizing.go(wire.dragContainer()); }; const mousedown = bind(wire.parent(), 'mousedown', event => { if (isRowBar(event.target)) { handler(event.target, 'top'); } if (isColBar(event.target)) { handler(event.target, 'left'); } }); const isRoot = e => { return eq$1(e, wire.view()); }; const findClosestEditableTable = target => closest$1(target, 'table', isRoot).filter(isEditable$1); const mouseover = bind(wire.view(), 'mouseover', event => { findClosestEditableTable(event.target).fold(() => { if (inBody(event.target)) { destroy(wire); } }, table => { if (resizing.isActive()) { hoverTable = Optional.some(table); refresh(wire, table); } }); }); const destroy$1 = () => { mousedown.unbind(); mouseover.unbind(); resizing.destroy(); destroy(wire); }; const refresh$1 = tbl => { refresh(wire, tbl); }; const events = create$1({ adjustHeight: Event([ 'table', 'delta', 'row' ]), adjustWidth: Event([ 'table', 'delta', 'column' ]), startAdjust: Event([]) }); return { destroy: destroy$1, refresh: refresh$1, on: resizing.on, off: resizing.off, hideBars: curry(hide, wire), showBars: curry(show, wire), events: events.registry }; }; const create = (wire, resizing, lazySizing) => { const hdirection = height; const vdirection = width; const manager = BarManager(wire); const events = create$1({ beforeResize: Event([ 'table', 'type' ]), afterResize: Event([ 'table', 'type' ]), startDrag: Event([]) }); manager.events.adjustHeight.bind(event => { const table = event.table; events.trigger.beforeResize(table, 'row'); const delta = hdirection.delta(event.delta, table); adjustHeight(table, delta, event.row); events.trigger.afterResize(table, 'row'); }); manager.events.startAdjust.bind(_event => { events.trigger.startDrag(); }); manager.events.adjustWidth.bind(event => { const table = event.table; events.trigger.beforeResize(table, 'col'); const delta = vdirection.delta(event.delta, table); const tableSize = lazySizing(table); adjustWidth(table, delta, event.column, resizing, tableSize); events.trigger.afterResize(table, 'col'); }); return { on: manager.on, off: manager.off, refreshBars: manager.refresh, hideBars: manager.hideBars, showBars: manager.showBars, destroy: manager.destroy, events: events.registry }; }; const TableResize = { create }; const random = () => window.crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295; let unique = 0; const generate = prefix => { const date = new Date(); const time = date.getTime(); const random$1 = Math.floor(random() * 1000000000); unique++; return prefix + '_' + random$1 + unique + String(time); }; const only = (element, isResizable) => { const parent = isDocument(element) ? documentElement(element) : element; return { parent: constant(parent), view: constant(element), dragContainer: constant(parent), origin: constant(SugarPosition(0, 0)), isResizable }; }; const detached = (editable, chrome, isResizable) => { const origin = () => absolute(chrome); return { parent: constant(chrome), view: constant(editable), dragContainer: constant(chrome), origin, isResizable }; }; const body = (editable, chrome, isResizable) => { return { parent: constant(chrome), view: constant(editable), dragContainer: constant(chrome), origin: constant(SugarPosition(0, 0)), isResizable }; }; const scrollable = (editable, chrome, dragContainer, isResizable) => { return { parent: constant(chrome), view: constant(editable), dragContainer: constant(dragContainer), origin: () => absolute(chrome), isResizable }; }; const ResizeWire = { only, detached, body, scrollable }; const createContainer = position => { const id = generate('resizer-container'); const container = SugarElement.fromTag('div'); set$2(container, 'id', id); setAll(container, { position, height: '0', width: '0', padding: '0', margin: '0', border: '0' }); return container; }; const getInlineResizeWire = (editor, isResizable) => { const isSplitUiMode$1 = isSplitUiMode(editor); const editorBody = SugarElement.fromDom(editor.getBody()); const container = createContainer(isSplitUiMode$1 ? 'relative' : 'static'); const body = body$1(); if (isSplitUiMode$1) { after$5(editorBody, container); return ResizeWire.scrollable(editorBody, container, body, isResizable); } append$1(body, container); return ResizeWire.body(editorBody, container, isResizable); }; const get = (editor, isResizable) => { if (editor.inline) { return getInlineResizeWire(editor, isResizable); } return ResizeWire.only(SugarElement.fromDom(editor.getDoc()), isResizable); }; const remove = (editor, wire) => { if (editor.inline) { remove$6(wire.parent()); } }; const isTable = node => isNonNullable(node) && node.nodeName === 'TABLE'; const barResizerPrefix = 'bar-'; const isResizable = elm => get$b(elm, 'data-mce-resize') !== 'false'; const syncTableCellPixels = table => { const warehouse = Warehouse.fromTable(table); if (!Warehouse.hasColumns(warehouse)) { each$2(cells$1(table), cell => { const computedWidth = get$a(cell, 'width'); set$1(cell, 'width', computedWidth); remove$7(cell, 'width'); }); } }; const isCornerResize = origin => startsWith(origin, 'corner-'); const getCornerLocation = origin => removeLeading(origin, 'corner-'); const TableResizeHandler = editor => { const selectionRng = value(); const tableResize = value(); const resizeWire = value(); let startW; let startRawW; let startH; let startRawH; const lazySizing = table => get$5(editor, table); const lazyResizingBehaviour = () => isPreserveTableColumnResizing(editor) ? preserveTable() : resizeTable(); const getNumColumns = table => getGridSize(table).columns; const getNumRows = table => getGridSize(table).rows; const afterCornerResize = (table, origin, width, height) => { const location = getCornerLocation(origin); const isRightEdgeResize = endsWith(location, 'e'); const isNorthEdgeResize = startsWith(location, 'n'); if (startRawW === '') { convertToPercentSizeWidth(table); } if (startRawH === '') { convertToPixelSizeHeight(table); } if (width !== startW && startRawW !== '') { set$1(table, 'width', startRawW); const resizing = lazyResizingBehaviour(); const tableSize = lazySizing(table); const col = isPreserveTableColumnResizing(editor) || isRightEdgeResize ? getNumColumns(table) - 1 : 0; adjustWidth(table, width - startW, col, resizing, tableSize); } else if (isPercentage$1(startRawW)) { const percentW = parseFloat(startRawW.replace('%', '')); const targetPercentW = width * percentW / startW; set$1(table, 'width', targetPercentW + '%'); } if (isPixel(startRawW)) { syncTableCellPixels(table); } if (height !== startH && startRawH !== '') { set$1(table, 'height', startRawH); const idx = isNorthEdgeResize ? 0 : getNumRows(table) - 1; adjustHeight(table, height - startH, idx); } }; const destroy = () => { tableResize.on(sz => { sz.destroy(); }); resizeWire.on(w => { remove(editor, w); }); }; editor.on('init', () => { const rawWire = get(editor, isResizable); resizeWire.set(rawWire); if (hasTableObjectResizing(editor) && hasTableResizeBars(editor)) { const resizing = lazyResizingBehaviour(); const sz = TableResize.create(rawWire, resizing, lazySizing); if (!editor.mode.isReadOnly()) { sz.on(); } sz.events.startDrag.bind(_event => { selectionRng.set(editor.selection.getRng()); }); sz.events.beforeResize.bind(event => { const rawTable = event.table.dom; fireObjectResizeStart(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type); }); sz.events.afterResize.bind(event => { const table = event.table; const rawTable = table.dom; removeDataStyle(table); selectionRng.on(rng => { editor.selection.setRng(rng); editor.focus(); }); fireObjectResized(editor, rawTable, getPixelWidth(rawTable), getPixelHeight(rawTable), barResizerPrefix + event.type); editor.undoManager.add(); }); tableResize.set(sz); } }); editor.on('ObjectResizeStart', e => { const targetElm = e.target; if (isTable(targetElm) && !editor.mode.isReadOnly()) { const table = SugarElement.fromDom(targetElm); each$2(editor.dom.select('.mce-clonedresizable'), clone => { editor.dom.addClass(clone, 'mce-' + getTableColumnResizingBehaviour(editor) + '-columns'); }); if (!isPixelSizing(table) && isTablePixelsForced(editor)) { convertToPixelSizeWidth(table); } else if (!isPercentSizing(table) && isTablePercentagesForced(editor)) { convertToPercentSizeWidth(table); } if (isNoneSizing(table) && startsWith(e.origin, barResizerPrefix)) { convertToPercentSizeWidth(table); } startW = e.width; startRawW = isTableResponsiveForced(editor) ? '' : getRawWidth(editor, targetElm).getOr(''); startH = e.height; startRawH = getRawHeight(editor, targetElm).getOr(''); } }); editor.on('ObjectResized', e => { const targetElm = e.target; if (isTable(targetElm)) { const table = SugarElement.fromDom(targetElm); const origin = e.origin; if (isCornerResize(origin)) { afterCornerResize(table, origin, e.width, e.height); } removeDataStyle(table); fireTableModified(editor, table.dom, styleModified); } }); const showResizeBars = () => { tableResize.on(resize => { resize.on(); resize.showBars(); }); }; const hideResizeBars = () => { tableResize.on(resize => { resize.off(); resize.hideBars(); }); }; editor.on('DisabledStateChange', e => { e.state ? hideResizeBars() : showResizeBars(); }); editor.on('SwitchMode', () => { editor.mode.isReadOnly() ? hideResizeBars() : showResizeBars(); }); editor.on('dragstart dragend', e => { e.type === 'dragstart' ? hideResizeBars() : showResizeBars(); }); editor.on('remove', () => { destroy(); }); const refresh = table => { tableResize.on(resize => resize.refreshBars(SugarElement.fromDom(table))); }; const hide = () => { tableResize.on(resize => resize.hideBars()); }; const show = () => { tableResize.on(resize => resize.showBars()); }; return { refresh, hide, show }; }; const setupTable = editor => { register(editor); const resizeHandler = TableResizeHandler(editor); const cellSelectionHandler = TableCellSelectionHandler(editor, resizeHandler); const actions = TableActions(editor, resizeHandler, cellSelectionHandler); registerCommands(editor, actions); registerQueryCommands(editor, actions); registerEvents(editor, actions); return { getSelectedCells: cellSelectionHandler.getSelectedCells, clearSelectedCells: cellSelectionHandler.clearSelectedCells }; }; const DomModel = editor => { const table = setupTable(editor); return { table }; }; var Model = () => { global$1.add('dom', DomModel); }; Model(); })(); PKr\tn55 M_videos.phpnu[PKr\jmu u qM_admission_phases.phpnu[PKr\^r ,M_class_groups.phpnu[PKr\ EyyjM_employees.phpnu[PKr\A6LL";M_image_sliders.phpnu[PKr\`r r BM_menus.phpnu[PKr\hg^MM_buildings.phpnu[PKr\nWDD 7UM_links.phpnu[PKr\ aa ]M_pages.phpnu[PKr\n*  RfM_class_group_settings.phpnu[PKr\x qM_majors.phpnu[PKr\N   zM_user_privileges.phpnu[PKr\_< M_academic_years.phpnu[PKr\ZpS S <M_scholarships.phpnu[PKr\W11ўpublic/M_posts.phpnu[PKr\sh2//!public/M_class_group_students.phpnu[PKr\C98Bpublic/M_students.phpnu[PKr\M nM_answers.phpnu[PKr\dwM_user_students.phpnu[PKr\{:zM_student_groups.phpnu[PKr\ZQ Q M_posts.phpnu[PKr\ãiS S + M_messages.phpnu[PKr\6X}gg M_banners.phpnu[PKr\G G `M_settings.phpnu[PKr\p # #'M_registrants.phpnu[PKr\3b  FKM_themes.phpnu[PKr\72Y Y TM_post_categories.phpnu[PKr\'f  (^M_dashboard.phpnu[PKr\漠 rdM_albums.phpnu[PKr\4