From 39b553529d166f87fe43ae01ee0ee986967689e7 Mon Sep 17 00:00:00 2001 From: harukin Date: Sun, 25 Nov 2018 23:36:59 +0900 Subject: [PATCH 01/24] add manifest.json --- manifest.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 manifest.json diff --git a/manifest.json b/manifest.json new file mode 100644 index 000000000..e6b8a0569 --- /dev/null +++ b/manifest.json @@ -0,0 +1,15 @@ +{ + "short_name": "Harukin+", + "name": "Harukin+!", + "icons": [ + { + "src": "icon.png", + "type": "image/png", + "sizes": "192x192" + } + ], + "start_url": "/", + "background_color": "#fff", + "theme_color": "#004898", + "display": "standalone" +} \ No newline at end of file From 8e25c091f4c10494e0c7a4c026f80070eaeabc4a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 22 Nov 2018 04:03:58 +0000 Subject: [PATCH 02/24] no mention notifications from mastodon (and pleroma) (cherry picked from commit ea235c0c6751b682332b968b4c18f905e8ece451) --- include/items.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/items.php b/include/items.php index d8a9e8e56..a679ebf3f 100755 --- a/include/items.php +++ b/include/items.php @@ -2643,7 +2643,7 @@ function tag_deliver($uid, $item_id) { if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) { foreach($matches as $match) { $matched_forums ++; - if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) { + if($term['url'] === $match[1] && intval($term['ttype']) === TERM_MENTION) { if($matched_forums <= $max_forums) { $plustagged = true; $found = true; @@ -2657,7 +2657,7 @@ function tag_deliver($uid, $item_id) { if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { foreach($matches as $match) { $matched_forums ++; - if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) { + if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) { if($matched_forums <= $max_forums) { $plustagged = true; $found = true; @@ -2893,7 +2893,7 @@ function tgroup_check($uid, $item) { if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) { foreach($matches as $match) { $matched_forums ++; - if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) { + if($term['url'] === $match[1] && intval($term['ttype']) === TERM_MENTION) { if($matched_forums <= $max_forums) { $found = true; break; @@ -2906,7 +2906,7 @@ function tgroup_check($uid, $item) { if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { foreach($matches as $match) { $matched_forums ++; - if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) { + if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) { if($matched_forums <= $max_forums) { $found = true; break; From 4010ea814a190e72ed99a32723db1f59e7b6542a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 22 Nov 2018 04:25:59 +0000 Subject: [PATCH 03/24] fix mastodon tag notifications (again) (cherry picked from commit 8e713245144d0bcedca0d3345017b5fa232c8ca3) --- include/items.php | 52 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/include/items.php b/include/items.php index a679ebf3f..c1613ea8c 100755 --- a/include/items.php +++ b/include/items.php @@ -2625,42 +2625,43 @@ function tag_deliver($uid, $item_id) { $plustagged = false; $matches = array(); - $pattern = '/[\!@]\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/'; + $pattern = '/[\!@]\!?\[[uz]rl\=' . preg_quote($term['url'],'/') . '\](.*?)\[\/[uz]rl\]/'; if(preg_match($pattern,$body,$matches)) $tagged = true; - // original red forum tagging sequence @forumname+ + $pattern = '/\[url\=' . preg_quote($term['url'],'/') . '\]\@(.*?)\[\/url\]/'; + if(preg_match($pattern,$body,$matches)) + $tagged = true; + + // standard forum tagging sequence !forumname - $pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/'; + $forumpattern = '/\!\!?\[[uz]rl\=([^\]]*?)\]((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/'; - $forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/'; + $forumpattern2 = '/\[[uz]rl\=([^\]]*?)\]\!((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/'; - $found = false; $matches = array(); - if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) { - foreach($matches as $match) { - $matched_forums ++; - if($term['url'] === $match[1] && intval($term['ttype']) === TERM_MENTION) { - if($matched_forums <= $max_forums) { - $plustagged = true; - $found = true; - break; - } - logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); - } - } - } - if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { foreach($matches as $match) { $matched_forums ++; if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) { if($matched_forums <= $max_forums) { $plustagged = true; - $found = true; + break; + } + logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); + } + } + } + + if(preg_match_all($forumpattern2,$body,$matches,PREG_SET_ORDER)) { + foreach($matches as $match) { + $matched_forums ++; + if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) { + if($matched_forums <= $max_forums) { + $plustagged = true; break; } logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring'); @@ -2882,18 +2883,19 @@ function tgroup_check($uid, $item) { $body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']); - $pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/'; - $forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/'; + $forumpattern2 = '/\[zrl\=([^\]]*?)\]\!((?:.(?!\[zrl\=))*?)\[\/zrl\]/'; + + $found = false; $matches = array(); - if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) { + if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { foreach($matches as $match) { $matched_forums ++; - if($term['url'] === $match[1] && intval($term['ttype']) === TERM_MENTION) { + if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) { if($matched_forums <= $max_forums) { $found = true; break; @@ -2903,7 +2905,7 @@ function tgroup_check($uid, $item) { } } - if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) { + if(preg_match_all($forumpattern2,$body,$matches,PREG_SET_ORDER)) { foreach($matches as $match) { $matched_forums ++; if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) { From 863cae1bab2749f2a829d01989dd501cb4742e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Jim=C3=A9nez=20Friaza?= Date: Sat, 24 Nov 2018 12:23:20 +0000 Subject: [PATCH 04/24] Update es-es (cherry picked from commit ca98a566ee7821c901b6a1db3013f3e9097747bc) --- view/es-es/hmessages.po | 26 +++++++++++++------------- view/es-es/hstrings.php | 28 ++++++++++++++-------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/view/es-es/hmessages.po b/view/es-es/hmessages.po index 3b42394b1..67cb21672 100644 --- a/view/es-es/hmessages.po +++ b/view/es-es/hmessages.po @@ -15,7 +15,7 @@ msgstr "" "Project-Id-Version: hubzilla\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-10-19 11:04+0200\n" -"PO-Revision-Date: 2018-10-24 11:35+0000\n" +"PO-Revision-Date: 2018-11-21 11:04+0000\n" "Last-Translator: Manuel Jiménez Friaza \n" "Language-Team: Spanish (Spain) (http://www.transifex.com/Friendica/hubzilla/language/es_ES/)\n" "MIME-Version: 1.0\n" @@ -1729,7 +1729,7 @@ msgstr "Importar elementos" #: ../../Zotlabs/Module/Import_items.php:126 msgid "" "Use this form to import existing posts and content from an export file." -msgstr "Utilice este formulario para importar entradas existentes y contenido desde un archivo de exportación." +msgstr "Utilice este formulario para importar entradas y contenido desde un archivo de exportación." #: ../../Zotlabs/Module/Import_items.php:127 #: ../../Zotlabs/Module/Import.php:548 @@ -1807,7 +1807,7 @@ msgstr "Un canal es una identidad única en la red. Puede representar a una pers #: ../../Zotlabs/Module/New_channel.php:183 msgid "" "or import an existing channel from another location." -msgstr "O importar un canal existente desde otro lugar." +msgstr "O importar un canal desde otro lugar." #: ../../Zotlabs/Module/New_channel.php:188 msgid "Validate" @@ -4496,7 +4496,7 @@ msgid "" "Leave blank to keep your existing channel nickname. You will be randomly " "assigned a similar nickname if either name is already allocated on this " "site." -msgstr "Dejar en blanco para mantener su alias de canal existente. Se le asignará aleatoriamente uno similar si cualquiera de los dos nombres ya está asignado en este sitio." +msgstr "Dejar en blanco para mantener su alias de canal . Se le asignará aleatoriamente uno similar si cualquiera de los dos nombres ya está asignado en este sitio." #: ../../Zotlabs/Module/Import.php:562 msgid "" @@ -4942,7 +4942,7 @@ msgstr "Introducir un nombre de álbum" #: ../../Zotlabs/Module/Photos.php:698 msgid "or select an existing album (doubleclick)" -msgstr "o seleccionar uno existente (doble click)" +msgstr "o seleccionar un álbum (con un doble click)" #: ../../Zotlabs/Module/Photos.php:699 msgid "Create a status post for this upload" @@ -5010,7 +5010,7 @@ msgstr "Introducir un nuevo nombre de álbum" #: ../../Zotlabs/Module/Photos.php:1067 msgid "or select an existing one (doubleclick)" -msgstr "o seleccionar uno (doble click) existente" +msgstr "o seleccionar un álbum (con un doble click)" #: ../../Zotlabs/Module/Photos.php:1072 msgid "Add a Tag" @@ -5557,7 +5557,7 @@ msgstr "Usar una foto de sus álbumes" #: ../../Zotlabs/Module/Profile_photo.php:474 #: ../../Zotlabs/Module/Cover_photo.php:409 msgid "Select existing photo" -msgstr "Seleccionar una foto existente" +msgstr "Seleccionar una foto" #: ../../Zotlabs/Module/Profile_photo.php:493 #: ../../Zotlabs/Module/Cover_photo.php:426 @@ -8443,7 +8443,7 @@ msgid "" "A deleted group with this name was revived. Existing item permissions " "may apply to this group and any future members. If this is " "not what you intended, please create another group with a different name." -msgstr "Un grupo suprimido con este nombre ha sido restablecido. Es posible que los permisos existentes sean aplicados a este grupo y sus futuros miembros. Si no quiere esto, por favor cree otro grupo con un nombre diferente." +msgstr "Un grupo suprimido con este nombre ha sido restablecido. Es posible que los permisos que ya existen sean aplicados a este grupo y sus futuros miembros. Si no quiere esto, por favor cree otro grupo con un nombre diferente." #: ../../Zotlabs/Lib/Group.php:270 ../../include/group.php:264 msgid "Add new connections to this privacy group" @@ -11149,11 +11149,11 @@ msgstr "Por favor visite el sitio web de $Projectname" #: ../../addon/upgrade_info/upgrade_info.php:46 msgid "app store" -msgstr "depósito de apps" +msgstr "aplicaciones disponibles" #: ../../addon/upgrade_info/upgrade_info.php:47 msgid "and install possibly missing apps." -msgstr "e instalar aplicaciones que posiblemente falten." +msgstr "e instale las aplicaciones que posiblemente falten." #: ../../addon/upgrade_info/upgrade_info.php:52 msgid "Upgrade Info" @@ -11364,7 +11364,7 @@ msgstr "Eliminar los datos de localización geográfica del navegador" #: ../../addon/hsse/hsse.php:99 ../../include/conversation.php:1302 msgid "Embed (existing) photo from your photo albums" -msgstr "Insertar (existente) foto de sus álbumes de fotos" +msgstr "Insertar una foto de sus álbumes" #: ../../addon/hsse/hsse.php:135 ../../include/conversation.php:1338 msgid "Tag term:" @@ -12247,7 +12247,7 @@ msgstr "Crear nuevos eventos aquí." msgid "" "You can accept new connections and change permissions for existing ones " "here. You can also e.g. create groups of contacts." -msgstr "Puede aceptar nuevas conexiones y cambiar permisos para las existentes aquí. También puede, por ejemplo, crear grupos de contactos." +msgstr "Puede aceptar nuevas conexiones y cambiar permisos para las que ya existen aquí. También puede, por ejemplo, crear grupos de contactos." #: ../../addon/tour/tour.php:82 msgid "System notifications will arrive here" @@ -14455,7 +14455,7 @@ msgstr "Etiquetas de la comunidad" #: ../../include/features.php:143 msgid "Ability to tag existing posts" -msgstr "Capacidad de etiquetar entradas existentes" +msgstr "Capacidad de etiquetar entradas" #: ../../include/features.php:150 msgid "Emoji Reactions" diff --git a/view/es-es/hstrings.php b/view/es-es/hstrings.php index a459e10dd..67f499feb 100644 --- a/view/es-es/hstrings.php +++ b/view/es-es/hstrings.php @@ -2,10 +2,10 @@ if(! function_exists("string_plural_select_es_es")) { function string_plural_select_es_es($n){ - return ($n != 1 ? 1 : 0); + return ($n != 1 ? 1 : 0);; }} App::$rtl = 0; -App::$strings["plural_function_code"] = "(n != 1 ? 1 : 0)"; +App::$strings["plural_function_code"] = "(n != 1 ? 1 : 0);"; App::$strings["Can view my channel stream and posts"] = "Pueden verse la actividad y publicaciones de mi canal"; App::$strings["Can send me their channel stream and posts"] = "Se me pueden enviar entradas y contenido de un canal"; App::$strings["Can view my default channel profile"] = "Puede verse mi perfil de canal predeterminado."; @@ -300,7 +300,7 @@ App::$strings["Imported file is empty."] = "El fichero importado está vacío."; App::$strings["Warning: Database versions differ by %1\$d updates."] = "Atención: Las versiones de la base de datos difieren en %1\$d actualizaciones."; App::$strings["Import completed"] = "Importación completada"; App::$strings["Import Items"] = "Importar elementos"; -App::$strings["Use this form to import existing posts and content from an export file."] = "Utilice este formulario para importar entradas existentes y contenido desde un archivo de exportación."; +App::$strings["Use this form to import existing posts and content from an export file."] = "Utilice este formulario para importar entradas y contenido desde un archivo de exportación."; App::$strings["File to Upload"] = "Fichero para subir"; App::$strings["You have created %1$.0f of %2$.0f allowed channels."] = "Ha creado %1$.0f de %2$.0f canales permitidos."; App::$strings["Loading"] = "Cargando"; @@ -315,7 +315,7 @@ App::$strings["Select a channel permission role compatible with your usage needs App::$strings["Read more about channel permission roles"] = "Leer más sobre los roles y permisos"; App::$strings["Create a Channel"] = "Crear un canal"; App::$strings["A channel is a unique network identity. It can represent a person (social network profile), a forum (group), a business or celebrity page, a newsfeed, and many other things."] = "Un canal es una identidad única en la red. Puede representar a una persona (un perfil de una red social), un foro o grupo, un negocio o una página de una celebridad, un \"feed\" de noticias, y muchas otras cosas."; -App::$strings["or import an existing channel from another location."] = "O importar un canal existente desde otro lugar."; +App::$strings["or import an existing channel from another location."] = "O importar un canal desde otro lugar."; App::$strings["Validate"] = "Validar"; App::$strings["Channel removals are not allowed within 48 hours of changing the account password."] = "La eliminación de canales no está permitida hasta pasadas 48 horas desde el último cambio de contraseña."; App::$strings["Remove This Channel"] = "Eliminar este canal"; @@ -914,7 +914,7 @@ App::$strings["For either option, please choose whether to make this hub your ne App::$strings["Make this hub my primary location"] = "Convertir este servidor en mi ubicación primaria"; App::$strings["Move this channel (disable all previous locations)"] = "Mover este canal (desactivar todas las ubicaciones anteriores)"; App::$strings["Use this channel nickname instead of the one provided"] = "Usa este alias de canal en lugar del que se proporciona"; -App::$strings["Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site."] = "Dejar en blanco para mantener su alias de canal existente. Se le asignará aleatoriamente uno similar si cualquiera de los dos nombres ya está asignado en este sitio."; +App::$strings["Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site."] = "Dejar en blanco para mantener su alias de canal . Se le asignará aleatoriamente uno similar si cualquiera de los dos nombres ya está asignado en este sitio."; App::$strings["This process may take several minutes to complete. Please submit the form only once and leave this page open until finished."] = "Este proceso puede tardar varios minutos en completarse. Por favor envíe el formulario una sola vez y mantenga esta página abierta hasta que termine."; App::$strings["Authentication failed."] = "Falló la autenticación."; App::$strings["Remote Authentication"] = "Acceso desde su servidor"; @@ -1014,7 +1014,7 @@ App::$strings["%1$.2f MB of %2$.2f MB photo storage used."] = "%1$.2f MB de %2$. App::$strings["%1$.2f MB photo storage used."] = "%1$.2f MB de almacenamiento de fotos utilizado."; App::$strings["Upload Photos"] = "Subir fotos"; App::$strings["Enter an album name"] = "Introducir un nombre de álbum"; -App::$strings["or select an existing album (doubleclick)"] = "o seleccionar uno existente (doble click)"; +App::$strings["or select an existing album (doubleclick)"] = "o seleccionar un álbum (con un doble click)"; App::$strings["Create a status post for this upload"] = "Crear un mensaje de estado para esta subida"; App::$strings["Description (optional)"] = "Descripción (opcional)"; App::$strings["Show Newest First"] = "Mostrar lo más reciente primero"; @@ -1031,7 +1031,7 @@ App::$strings["Rotate CW (right)"] = "Girar CW (a la derecha)"; App::$strings["Rotate CCW (left)"] = "Girar CCW (a la izquierda)"; App::$strings["Move photo to album"] = "Mover la foto a un álbum"; App::$strings["Enter a new album name"] = "Introducir un nuevo nombre de álbum"; -App::$strings["or select an existing one (doubleclick)"] = "o seleccionar uno (doble click) existente"; +App::$strings["or select an existing one (doubleclick)"] = "o seleccionar un álbum (con un doble click)"; App::$strings["Add a Tag"] = "Añadir una etiqueta"; App::$strings["Example: @bob, @Barbara_Jensen, @jim@example.com"] = "Ejemplos: @eva, @Carmen_Osuna, @jaime@ejemplo.com"; App::$strings["Flag as adult in album view"] = "Marcar como \"solo para adultos\" en el álbum"; @@ -1153,7 +1153,7 @@ App::$strings["Use Photo for Profile"] = "Usar la fotografía para el perfil"; App::$strings["Change Profile Photo"] = "Cambiar la foto del perfil"; App::$strings["Use"] = "Usar"; App::$strings["Use a photo from your albums"] = "Usar una foto de sus álbumes"; -App::$strings["Select existing photo"] = "Seleccionar una foto existente"; +App::$strings["Select existing photo"] = "Seleccionar una foto"; App::$strings["Crop Image"] = "Recortar imagen"; App::$strings["Please adjust the image cropping for optimum viewing."] = "Por favor ajuste el recorte de la imagen para una visión óptima."; App::$strings["Done Editing"] = "Edición completada"; @@ -1829,7 +1829,7 @@ App::$strings["Directory Options"] = "Opciones del directorio"; App::$strings["Safe Mode"] = "Modo seguro"; App::$strings["Public Forums Only"] = "Solo foros públicos"; App::$strings["This Website Only"] = "Solo este sitio web"; -App::$strings["A deleted group with this name was revived. Existing item permissions may apply to this group and any future members. If this is not what you intended, please create another group with a different name."] = "Un grupo suprimido con este nombre ha sido restablecido. Es posible que los permisos existentes sean aplicados a este grupo y sus futuros miembros. Si no quiere esto, por favor cree otro grupo con un nombre diferente."; +App::$strings["A deleted group with this name was revived. Existing item permissions may apply to this group and any future members. If this is not what you intended, please create another group with a different name."] = "Un grupo suprimido con este nombre ha sido restablecido. Es posible que los permisos que ya existen sean aplicados a este grupo y sus futuros miembros. Si no quiere esto, por favor cree otro grupo con un nombre diferente."; App::$strings["Add new connections to this privacy group"] = "Añadir conexiones nuevas a este grupo de canales"; App::$strings["edit"] = "editar"; App::$strings["Edit group"] = "Editar grupo"; @@ -2458,8 +2458,8 @@ App::$strings["Jappix Mini Settings"] = "Ajustes de Jappix Mini"; App::$strings["Your channel has been upgraded to the latest \$Projectname version."] = "Su canal ha sido actualizado a la última versión de \$Projectname."; App::$strings["To improve usability, we have converted some features into installable stand-alone apps."] = "Para mejorar la usabilidad, hemos convertido algunas características en aplicaciones independientes instalables."; App::$strings["Please visit the \$Projectname"] = "Por favor visite el sitio web de \$Projectname"; -App::$strings["app store"] = "depósito de apps"; -App::$strings["and install possibly missing apps."] = "e instalar aplicaciones que posiblemente falten."; +App::$strings["app store"] = "aplicaciones disponibles"; +App::$strings["and install possibly missing apps."] = "e instale las aplicaciones que posiblemente falten."; App::$strings["Upgrade Info"] = "Información de actualización"; App::$strings["Do not show this again"] = "No mostrar esto de nuevo"; App::$strings["Access Denied"] = "Acceso denegado"; @@ -2509,7 +2509,7 @@ App::$strings["WYSIWYG status editor"] = "Editor de estado de WYSIWYG"; App::$strings["WYSIWYG Status"] = "Estado de WYSIWYG"; App::$strings["Set your location"] = "Establecer su ubicación"; App::$strings["Clear browser location"] = "Eliminar los datos de localización geográfica del navegador"; -App::$strings["Embed (existing) photo from your photo albums"] = "Insertar (existente) foto de sus álbumes de fotos"; +App::$strings["Embed (existing) photo from your photo albums"] = "Insertar una foto de sus álbumes"; App::$strings["Tag term:"] = "Término de la etiqueta:"; App::$strings["Where are you right now?"] = "¿Donde está ahora?"; App::$strings["Choose a different album..."] = "Elegir un álbum diferente..."; @@ -2706,7 +2706,7 @@ App::$strings["Click here to see activity from your connections."] = "Pulsar aqu App::$strings["Click here to see your channel home."] = "Pulsar aquí para ver la página de inicio de su canal."; App::$strings["You can access your private messages from here."] = "Puede acceder a sus mensajes privados desde aquí."; App::$strings["Create new events here."] = "Crear nuevos eventos aquí."; -App::$strings["You can accept new connections and change permissions for existing ones here. You can also e.g. create groups of contacts."] = "Puede aceptar nuevas conexiones y cambiar permisos para las existentes aquí. También puede, por ejemplo, crear grupos de contactos."; +App::$strings["You can accept new connections and change permissions for existing ones here. You can also e.g. create groups of contacts."] = "Puede aceptar nuevas conexiones y cambiar permisos para las que ya existen aquí. También puede, por ejemplo, crear grupos de contactos."; App::$strings["System notifications will arrive here"] = "Las notificaciones del sistema llegarán aquí"; App::$strings["Search for content and users"] = "Buscar contenido y usuarios"; App::$strings["Browse for new contacts"] = "Buscar nuevos contactos"; @@ -3270,7 +3270,7 @@ App::$strings["Connection Filtering"] = "Filtrado de conexiones"; App::$strings["Filter incoming posts from connections based on keywords/content"] = "Filtrar publicaciones entrantes de conexiones por palabras clave o contenido"; App::$strings["Conversation"] = "Conversación"; App::$strings["Community Tagging"] = "Etiquetas de la comunidad"; -App::$strings["Ability to tag existing posts"] = "Capacidad de etiquetar entradas existentes"; +App::$strings["Ability to tag existing posts"] = "Capacidad de etiquetar entradas"; App::$strings["Emoji Reactions"] = "Emoticonos \"emoji\""; App::$strings["Add emoji reaction ability to posts"] = "Activar la capacidad de añadir un emoticono \"emoji\" a las entradas"; App::$strings["Dislike Posts"] = "Desagrado de publicaciones"; From a0d1ce77dc4a74f42cd68c682af8d2d0596cb754 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 25 Nov 2018 09:09:26 +0000 Subject: [PATCH 05/24] update imagesloaded to version 4.1.4 via composer (cherry picked from commit c667572d3eedb0c31b29a4c469b378ccdcee0ba1) --- composer.json | 3 +- composer.lock | 41 +- library/imagesloaded/imagesloaded.pkgd.min.js | 7 - vendor/composer/ClassLoader.php | 2 +- vendor/composer/LICENSE | 69 +--- vendor/composer/autoload_classmap.php | 6 +- vendor/composer/autoload_static.php | 5 +- vendor/composer/installed.json | 41 ++ vendor/desandro/imagesloaded/.gitignore | 5 + vendor/desandro/imagesloaded/.jshintrc | 12 + vendor/desandro/imagesloaded/README.md | 362 +++++++++++++++++ vendor/desandro/imagesloaded/bower.json | 37 ++ vendor/desandro/imagesloaded/composer.json | 15 + vendor/desandro/imagesloaded/contributing.md | 20 + vendor/desandro/imagesloaded/gulpfile.js | 128 ++++++ vendor/desandro/imagesloaded/imagesloaded.js | 377 ++++++++++++++++++ .../imagesloaded/imagesloaded.pkgd.js | 74 ++-- .../imagesloaded/imagesloaded.pkgd.min.js | 7 + vendor/desandro/imagesloaded/package.json | 48 +++ .../sandbox/background/css/background.css | 29 ++ .../sandbox/background/index.html | 51 +++ .../imagesloaded/sandbox/progress/index.html | 89 +++++ .../imagesloaded/sandbox/progress/progress.js | 111 ++++++ .../desandro/imagesloaded/test/css/tests.css | 41 ++ .../imagesloaded/test/img/blue-shell.jpg | Bin 0 -> 24555 bytes .../imagesloaded/test/img/bowser-jr.jpg | Bin 0 -> 36987 bytes .../imagesloaded/test/img/thunder-cloud.jpg | Bin 0 -> 24588 bytes vendor/desandro/imagesloaded/test/index.html | 104 +++++ .../desandro/imagesloaded/test/unit/append.js | 30 ++ .../imagesloaded/test/unit/background.js | 70 ++++ .../desandro/imagesloaded/test/unit/basics.js | 28 ++ .../imagesloaded/test/unit/data-uri.js | 10 + .../imagesloaded/test/unit/jquery-fail.js | 29 ++ .../imagesloaded/test/unit/jquery-success.js | 28 ++ .../imagesloaded/test/unit/local-files.js | 31 ++ .../imagesloaded/test/unit/no-images.js | 11 + .../imagesloaded/test/unit/non-element.js | 24 ++ .../imagesloaded/test/unit/selector-string.js | 12 + .../imagesloaded/test/unit/single-element.js | 11 + view/php/theme_init.php | 2 +- 40 files changed, 1871 insertions(+), 99 deletions(-) delete mode 100644 library/imagesloaded/imagesloaded.pkgd.min.js create mode 100644 vendor/desandro/imagesloaded/.gitignore create mode 100644 vendor/desandro/imagesloaded/.jshintrc create mode 100644 vendor/desandro/imagesloaded/README.md create mode 100644 vendor/desandro/imagesloaded/bower.json create mode 100644 vendor/desandro/imagesloaded/composer.json create mode 100644 vendor/desandro/imagesloaded/contributing.md create mode 100644 vendor/desandro/imagesloaded/gulpfile.js create mode 100644 vendor/desandro/imagesloaded/imagesloaded.js rename {library => vendor/desandro}/imagesloaded/imagesloaded.pkgd.js (89%) create mode 100644 vendor/desandro/imagesloaded/imagesloaded.pkgd.min.js create mode 100644 vendor/desandro/imagesloaded/package.json create mode 100644 vendor/desandro/imagesloaded/sandbox/background/css/background.css create mode 100644 vendor/desandro/imagesloaded/sandbox/background/index.html create mode 100644 vendor/desandro/imagesloaded/sandbox/progress/index.html create mode 100644 vendor/desandro/imagesloaded/sandbox/progress/progress.js create mode 100644 vendor/desandro/imagesloaded/test/css/tests.css create mode 100644 vendor/desandro/imagesloaded/test/img/blue-shell.jpg create mode 100644 vendor/desandro/imagesloaded/test/img/bowser-jr.jpg create mode 100644 vendor/desandro/imagesloaded/test/img/thunder-cloud.jpg create mode 100644 vendor/desandro/imagesloaded/test/index.html create mode 100644 vendor/desandro/imagesloaded/test/unit/append.js create mode 100644 vendor/desandro/imagesloaded/test/unit/background.js create mode 100644 vendor/desandro/imagesloaded/test/unit/basics.js create mode 100644 vendor/desandro/imagesloaded/test/unit/data-uri.js create mode 100644 vendor/desandro/imagesloaded/test/unit/jquery-fail.js create mode 100644 vendor/desandro/imagesloaded/test/unit/jquery-success.js create mode 100644 vendor/desandro/imagesloaded/test/unit/local-files.js create mode 100644 vendor/desandro/imagesloaded/test/unit/no-images.js create mode 100644 vendor/desandro/imagesloaded/test/unit/non-element.js create mode 100644 vendor/desandro/imagesloaded/test/unit/selector-string.js create mode 100644 vendor/desandro/imagesloaded/test/unit/single-element.js diff --git a/composer.json b/composer.json index f117cc3b1..e6cefa241 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,8 @@ "smarty/smarty": "~3.1", "ramsey/uuid": "^3.8", "twbs/bootstrap": "4.1.3", - "blueimp/jquery-file-upload": "^9.25" + "blueimp/jquery-file-upload": "^9.25", + "desandro/imagesloaded": "^4.1" }, "require-dev" : { "phpunit/phpunit" : "@stable", diff --git a/composer.lock b/composer.lock index d7e8d11f6..64d28c22e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "63d0e52cc07f8113059ec30d3637b850", + "content-hash": "fe5e71d7076eeddf1c174be4a5c052dd", "packages": [ { "name": "blueimp/jquery-file-upload", @@ -163,6 +163,45 @@ "description": "Internationalization library powered by CLDR data.", "time": "2017-12-29T00:13:05+00:00" }, + { + "name": "desandro/imagesloaded", + "version": "v4.1.4", + "source": { + "type": "git", + "url": "https://github.com/desandro/imagesloaded.git", + "reference": "67c4e57453120935180c45c6820e7d3fbd2ea1f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/desandro/imagesloaded/zipball/67c4e57453120935180c45c6820e7d3fbd2ea1f9", + "reference": "67c4e57453120935180c45c6820e7d3fbd2ea1f9", + "shasum": "" + }, + "type": "component", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David DeSandro", + "homepage": "http://desandro.com/", + "role": "developer" + } + ], + "description": "JavaScript is all like _You images done yet or what?_", + "homepage": "http://imagesloaded.desandro.com", + "keywords": [ + "dom", + "images", + "javascript", + "jquery-plugin", + "library", + "loaded", + "ui" + ], + "time": "2018-01-02T16:53:35+00:00" + }, { "name": "ezyang/htmlpurifier", "version": "v4.10.0", diff --git a/library/imagesloaded/imagesloaded.pkgd.min.js b/library/imagesloaded/imagesloaded.pkgd.min.js deleted file mode 100644 index c3e71fadc..000000000 --- a/library/imagesloaded/imagesloaded.pkgd.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * imagesLoaded PACKAGED v4.1.0 - * JavaScript is all like "You images are done yet or what?" - * MIT License - */ - -!function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||[];return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict";"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}(window,function(t,e){function i(t,e){for(var i in e)t[i]=e[i];return t}function n(t){var e=[];if(Array.isArray(t))e=t;else if("number"==typeof t.length)for(var i=0;iapcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE index f0157a6ed..f27399a04 100644 --- a/vendor/composer/LICENSE +++ b/vendor/composer/LICENSE @@ -1,56 +1,21 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: Composer -Upstream-Contact: Jordi Boggiano -Source: https://github.com/composer/composer -Files: * -Copyright: 2016, Nils Adermann - 2016, Jordi Boggiano -License: Expat +Copyright (c) Nils Adermann, Jordi Boggiano -Files: src/Composer/Util/TlsHelper.php -Copyright: 2016, Nils Adermann - 2016, Jordi Boggiano - 2013, Evan Coury -License: Expat and BSD-2-Clause +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: -License: BSD-2-Clause - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - . - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - . - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - . - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -License: Expat - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is furnished - to do so, subject to the following conditions: - . - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index f3c814e02..b7cffc67c 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -981,7 +981,6 @@ return array( 'Zotlabs\\Module\\Mood' => $baseDir . '/Zotlabs/Module/Mood.php', 'Zotlabs\\Module\\Network' => $baseDir . '/Zotlabs/Module/Network.php', 'Zotlabs\\Module\\New_channel' => $baseDir . '/Zotlabs/Module/New_channel.php', - 'Zotlabs\\Module\\Nojs' => $baseDir . '/Zotlabs/Module/Nojs.php', 'Zotlabs\\Module\\Notes' => $baseDir . '/Zotlabs/Module/Notes.php', 'Zotlabs\\Module\\Notifications' => $baseDir . '/Zotlabs/Module/Notifications.php', 'Zotlabs\\Module\\Notify' => $baseDir . '/Zotlabs/Module/Notify.php', @@ -1337,7 +1336,10 @@ return array( 'Zotlabs\\Update\\_1222' => $baseDir . '/Zotlabs/Update/_1222.php', 'Zotlabs\\Update\\_1223' => $baseDir . '/Zotlabs/Update/_1223.php', 'Zotlabs\\Update\\_1224' => $baseDir . '/Zotlabs/Update/_1224.php', - 'Zotlabs\\Web\\CheckJS' => $baseDir . '/Zotlabs/Web/CheckJS.php', + 'Zotlabs\\Update\\_1225' => $baseDir . '/Zotlabs/Update/_1225.php', + 'Zotlabs\\Update\\_1226' => $baseDir . '/Zotlabs/Update/_1226.php', + 'Zotlabs\\Update\\_1227' => $baseDir . '/Zotlabs/Update/_1227.php', + 'Zotlabs\\Update\\_1228' => $baseDir . '/Zotlabs/Update/_1228.php', 'Zotlabs\\Web\\Controller' => $baseDir . '/Zotlabs/Web/Controller.php', 'Zotlabs\\Web\\HTTPHeaders' => $baseDir . '/Zotlabs/Web/HTTPHeaders.php', 'Zotlabs\\Web\\HTTPSig' => $baseDir . '/Zotlabs/Web/HTTPSig.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index ce0232306..a02571a95 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -1149,7 +1149,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d 'Zotlabs\\Module\\Mood' => __DIR__ . '/../..' . '/Zotlabs/Module/Mood.php', 'Zotlabs\\Module\\Network' => __DIR__ . '/../..' . '/Zotlabs/Module/Network.php', 'Zotlabs\\Module\\New_channel' => __DIR__ . '/../..' . '/Zotlabs/Module/New_channel.php', - 'Zotlabs\\Module\\Nojs' => __DIR__ . '/../..' . '/Zotlabs/Module/Nojs.php', 'Zotlabs\\Module\\Notes' => __DIR__ . '/../..' . '/Zotlabs/Module/Notes.php', 'Zotlabs\\Module\\Notifications' => __DIR__ . '/../..' . '/Zotlabs/Module/Notifications.php', 'Zotlabs\\Module\\Notify' => __DIR__ . '/../..' . '/Zotlabs/Module/Notify.php', @@ -1506,7 +1505,9 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d 'Zotlabs\\Update\\_1223' => __DIR__ . '/../..' . '/Zotlabs/Update/_1223.php', 'Zotlabs\\Update\\_1224' => __DIR__ . '/../..' . '/Zotlabs/Update/_1224.php', 'Zotlabs\\Update\\_1225' => __DIR__ . '/../..' . '/Zotlabs/Update/_1225.php', - 'Zotlabs\\Web\\CheckJS' => __DIR__ . '/../..' . '/Zotlabs/Web/CheckJS.php', + 'Zotlabs\\Update\\_1226' => __DIR__ . '/../..' . '/Zotlabs/Update/_1226.php', + 'Zotlabs\\Update\\_1227' => __DIR__ . '/../..' . '/Zotlabs/Update/_1227.php', + 'Zotlabs\\Update\\_1228' => __DIR__ . '/../..' . '/Zotlabs/Update/_1228.php', 'Zotlabs\\Web\\Controller' => __DIR__ . '/../..' . '/Zotlabs/Web/Controller.php', 'Zotlabs\\Web\\HTTPHeaders' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPHeaders.php', 'Zotlabs\\Web\\HTTPSig' => __DIR__ . '/../..' . '/Zotlabs/Web/HTTPSig.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index af845828e..b9c998f12 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -162,6 +162,47 @@ ], "description": "Internationalization library powered by CLDR data." }, + { + "name": "desandro/imagesloaded", + "version": "v4.1.4", + "version_normalized": "4.1.4.0", + "source": { + "type": "git", + "url": "https://github.com/desandro/imagesloaded.git", + "reference": "67c4e57453120935180c45c6820e7d3fbd2ea1f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/desandro/imagesloaded/zipball/67c4e57453120935180c45c6820e7d3fbd2ea1f9", + "reference": "67c4e57453120935180c45c6820e7d3fbd2ea1f9", + "shasum": "" + }, + "time": "2018-01-02T16:53:35+00:00", + "type": "component", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David DeSandro", + "homepage": "http://desandro.com/", + "role": "developer" + } + ], + "description": "JavaScript is all like _You images done yet or what?_", + "homepage": "http://imagesloaded.desandro.com", + "keywords": [ + "dom", + "images", + "javascript", + "jquery-plugin", + "library", + "loaded", + "ui" + ] + }, { "name": "ezyang/htmlpurifier", "version": "v4.10.0", diff --git a/vendor/desandro/imagesloaded/.gitignore b/vendor/desandro/imagesloaded/.gitignore new file mode 100644 index 000000000..2486eb53d --- /dev/null +++ b/vendor/desandro/imagesloaded/.gitignore @@ -0,0 +1,5 @@ +bower_components/ +node_modules/ +_site/ +build/ +package-lock.json diff --git a/vendor/desandro/imagesloaded/.jshintrc b/vendor/desandro/imagesloaded/.jshintrc new file mode 100644 index 000000000..78aa4af7b --- /dev/null +++ b/vendor/desandro/imagesloaded/.jshintrc @@ -0,0 +1,12 @@ +{ + "browser": true, + "curly": true, + "newcap": false, + "strict": true, + "undef": true, + "unused": true, + "globals": { + "imagesLoaded": false, + "QUnit": false + } +} diff --git a/vendor/desandro/imagesloaded/README.md b/vendor/desandro/imagesloaded/README.md new file mode 100644 index 000000000..67b799dfd --- /dev/null +++ b/vendor/desandro/imagesloaded/README.md @@ -0,0 +1,362 @@ +# imagesLoaded + +

JavaScript is all like "You images done yet or what?"

+ +[imagesloaded.desandro.com](http://imagesloaded.desandro.com) + +Detect when images have been loaded. + +## Install + +### Download + ++ [imagesloaded.pkgd.min.js](https://unpkg.com/imagesloaded@4/imagesloaded.pkgd.min.js) minified ++ [imagesloaded.pkgd.js](https://unpkg.com/imagesloaded@4/imagesloaded.pkgd.js) un-minified + +### CDN + +``` html + + + +``` + +### Package managers + +Install via [npm](https://www.npmjs.com/package/imagesloaded): `npm install imagesloaded` + +Install via [Bower](http://bower.io): `bower install imagesloaded --save` + +## jQuery + +You can use imagesLoaded as a jQuery Plugin. + +``` js +$('#container').imagesLoaded( function() { + // images have loaded +}); + +// options +$('#container').imagesLoaded( { + // options... + }, + function() { + // images have loaded + } +); +``` + +`.imagesLoaded()` returns a [jQuery Deferred object](http://api.jquery.com/category/deferred-object/). This allows you to use `.always()`, `.done()`, `.fail()` and `.progress()`. + +``` js +$('#container').imagesLoaded() + .always( function( instance ) { + console.log('all images loaded'); + }) + .done( function( instance ) { + console.log('all images successfully loaded'); + }) + .fail( function() { + console.log('all images loaded, at least one is broken'); + }) + .progress( function( instance, image ) { + var result = image.isLoaded ? 'loaded' : 'broken'; + console.log( 'image is ' + result + ' for ' + image.img.src ); + }); +``` + +## Vanilla JavaScript + +You can use imagesLoaded with vanilla JS. + +``` js +imagesLoaded( elem, callback ) +// options +imagesLoaded( elem, options, callback ) +// you can use `new` if you like +new imagesLoaded( elem, callback ) +``` + ++ `elem` _Element, NodeList, Array, or Selector String_ ++ `options` _Object_ ++ `callback` _Function_ - function triggered after all images have been loaded + +Using a callback function is the same as binding it to the `always` event (see below). + +``` js +// element +imagesLoaded( document.querySelector('#container'), function( instance ) { + console.log('all images are loaded'); +}); +// selector string +imagesLoaded( '#container', function() {...}); +// multiple elements +var posts = document.querySelectorAll('.post'); +imagesLoaded( posts, function() {...}); +``` + +Bind events with vanilla JS with .on(), .off(), and .once() methods. + +``` js +var imgLoad = imagesLoaded( elem ); +function onAlways( instance ) { + console.log('all images are loaded'); +} +// bind with .on() +imgLoad.on( 'always', onAlways ); +// unbind with .off() +imgLoad.off( 'always', onAlways ); +``` + +## Background + +Detect when background images have loaded, in addition to ``s. + +Set `{ background: true }` to detect when the element's background image has loaded. + +``` js +// jQuery +$('#container').imagesLoaded( { background: true }, function() { + console.log('#container background image loaded'); +}); + +// vanilla JS +imagesLoaded( '#container', { background: true }, function() { + console.log('#container background image loaded'); +}); +``` + +[See jQuery demo](http://codepen.io/desandro/pen/pjVMPB) or [vanilla JS demo](http://codepen.io/desandro/pen/avKooW) on CodePen. + +Set to a selector string like `{ background: '.item' }` to detect when the background images of child elements have loaded. + +``` js +// jQuery +$('#container').imagesLoaded( { background: '.item' }, function() { + console.log('all .item background images loaded'); +}); + +// vanilla JS +imagesLoaded( '#container', { background: '.item' }, function() { + console.log('all .item background images loaded'); +}); +``` + +[See jQuery demo](http://codepen.io/desandro/pen/avKoZL) or [vanilla JS demo](http://codepen.io/desandro/pen/vNrBGz) on CodePen. + +## Events + +### always + +``` js +// jQuery +$('#container').imagesLoaded().always( function( instance ) { + console.log('ALWAYS - all images have been loaded'); +}); + +// vanilla JS +imgLoad.on( 'always', function( instance ) { + console.log('ALWAYS - all images have been loaded'); +}); +``` + +Triggered after all images have been either loaded or confirmed broken. + ++ `instance` _imagesLoaded_ - the imagesLoaded instance + +### done + +``` js +// jQuery +$('#container').imagesLoaded().done( function( instance ) { + console.log('DONE - all images have been successfully loaded'); +}); + +// vanilla JS +imgLoad.on( 'done', function( instance ) { + console.log('DONE - all images have been successfully loaded'); +}); +``` + +Triggered after all images have successfully loaded without any broken images. + +### fail + +``` js +$('#container').imagesLoaded().fail( function( instance ) { + console.log('FAIL - all images loaded, at least one is broken'); +}); + +// vanilla JS +imgLoad.on( 'fail', function( instance ) { + console.log('FAIL - all images loaded, at least one is broken'); +}); +``` + +Triggered after all images have been loaded with at least one broken image. + +### progress + +``` js +imgLoad.on( 'progress', function( instance, image ) { + var result = image.isLoaded ? 'loaded' : 'broken'; + console.log( 'image is ' + result + ' for ' + image.img.src ); +}); +``` + +Triggered after each image has been loaded. + ++ `instance` _imagesLoaded_ - the imagesLoaded instance ++ `image` _LoadingImage_ - the LoadingImage instance of the loaded image + + + +## Properties + +### LoadingImage.img + +_Image_ - The `img` element + +### LoadingImage.isLoaded + +_Boolean_ - `true` when the image has successfully loaded + +### imagesLoaded.images + +Array of _LoadingImage_ instances for each image detected + +``` js +var imgLoad = imagesLoaded('#container'); +imgLoad.on( 'always', function() { + console.log( imgLoad.images.length + ' images loaded' ); + // detect which image is broken + for ( var i = 0, len = imgLoad.images.length; i < len; i++ ) { + var image = imgLoad.images[i]; + var result = image.isLoaded ? 'loaded' : 'broken'; + console.log( 'image is ' + result + ' for ' + image.img.src ); + } +}); +``` + +## Browserify + +imagesLoaded works with [Browserify](http://browserify.org/). + +``` bash +npm install imagesloaded --save +``` + +``` js +var imagesLoaded = require('imagesloaded'); + +imagesLoaded( elem, function() {...} ); +``` + +Use `.makeJQueryPlugin` to make to use `.imagesLoaded()` jQuery plugin. + +``` js +var $ = require('jquery'); +var imagesLoaded = require('imagesloaded'); + +// provide jQuery argument +imagesLoaded.makeJQueryPlugin( $ ); +// now use .imagesLoaded() jQuery plugin +$('#container').imagesLoaded( function() {...}); +``` + +## Webpack + +Install imagesLoaded with npm. + +``` bash +npm install imagesloaded +``` + +You can then `require('imagesloaded')`. + +``` js +// main.js +var imagesLoaded = require('imagesloaded'); + +imagesLoaded( '#container', function() { + // images have loaded +}); +``` + +Use `.makeJQueryPlugin` to make `.imagesLoaded()` jQuery plugin. + +``` js +// main.js +var imagesLoaded = require('imagesloaded'); +var $ = require('jquery'); + +// provide jQuery argument +imagesLoaded.makeJQueryPlugin( $ ); +// now use .imagesLoaded() jQuery plugin +$('#container').imagesLoaded( function() {...}); +``` + +Run webpack. + +``` bash +webpack main.js bundle.js +``` + +## RequireJS + +imagesLoaded works with [RequireJS](http://requirejs.org). + +You can require [imagesloaded.pkgd.js](http://imagesloaded.desandro.com/imagesloaded.pkgd.js). + +``` js +requirejs( [ + 'path/to/imagesloaded.pkgd.js', +], function( imagesLoaded ) { + imagesLoaded( '#container', function() { ... }); +}); +``` + +Use `.makeJQueryPlugin` to make `.imagesLoaded()` jQuery plugin. + +``` js +requirejs( [ + 'jquery', + 'path/to/imagesloaded.pkgd.js', +], function( $, imagesLoaded ) { + // provide jQuery argument + imagesLoaded.makeJQueryPlugin( $ ); + // now use .imagesLoaded() jQuery plugin + $('#container').imagesLoaded( function() {...}); +}); +``` + +You can manage dependencies with [Bower](http://bower.io). Set `baseUrl` to `bower_components` and set a path config for all your application code. + +``` js +requirejs.config({ + baseUrl: 'bower_components/', + paths: { // path to your app + app: '../' + } +}); + +requirejs( [ + 'imagesloaded/imagesloaded', + 'app/my-component.js' +], function( imagesLoaded, myComp ) { + imagesLoaded( '#container', function() { ... }); +}); +``` + +## Browser support + ++ IE9+ ++ Android 2.3+ ++ iOS Safari 4+ ++ All other modern browsers + +Use [imagesLoaded v3](http://imagesloaded.desandro.com/v3/) for IE8 support. + +## MIT License + +imagesLoaded is released under the [MIT License](http://desandro.mit-license.org/). Have at it. diff --git a/vendor/desandro/imagesloaded/bower.json b/vendor/desandro/imagesloaded/bower.json new file mode 100644 index 000000000..795c69f07 --- /dev/null +++ b/vendor/desandro/imagesloaded/bower.json @@ -0,0 +1,37 @@ +{ + "name": "imagesloaded", + "description": "JavaScript is all like _You images done yet or what?_", + "main": "imagesloaded.js", + "dependencies": { + "ev-emitter": "^1.0.0" + }, + "devDependencies": { + "jquery": ">=1.9 <4.0", + "qunit": "^2.0.0" + }, + "ignore": [ + "**/.*", + "test", + "package.json", + "composer.json", + "node_modules", + "bower_components", + "tests", + "sandbox/", + "gulpfile.js", + "contributing.md" + ], + "homepage": "http://imagesloaded.desandro.com", + "authors": [ + "David DeSandro" + ], + "moduleType": [ + "amd", + "globals", + "node" + ], + "keywords": [ + "images" + ], + "license": "MIT" +} diff --git a/vendor/desandro/imagesloaded/composer.json b/vendor/desandro/imagesloaded/composer.json new file mode 100644 index 000000000..95ba64c4a --- /dev/null +++ b/vendor/desandro/imagesloaded/composer.json @@ -0,0 +1,15 @@ +{ + "name": "desandro/imagesloaded", + "description": "JavaScript is all like _You images done yet or what?_", + "type": "component", + "keywords": ["javascript", "library", "images", "loaded", "dom", "ui", "jquery-plugin"], + "homepage": "http://imagesloaded.desandro.com", + "license": "MIT", + "authors": [ + { + "name": "David DeSandro", + "homepage": "http://desandro.com/", + "role": "developer" + } + ] +} diff --git a/vendor/desandro/imagesloaded/contributing.md b/vendor/desandro/imagesloaded/contributing.md new file mode 100644 index 000000000..acac280cc --- /dev/null +++ b/vendor/desandro/imagesloaded/contributing.md @@ -0,0 +1,20 @@ +## Submitting issues + +### Reduced test case required + +All bug reports and problem issues require a [**reduced test case**](http://css-tricks.com/reduced-test-cases/). + ++ A reduced test case clearly demonstrates the bug or issue. ++ It contains the bare minimum HTML, CSS, and JavaScript required to demonstrate the bug. ++ A link to your production site is **not** a reduced test case. + +Create a test case by forking a [CodePen demos](http://codepen.io/desandro/pens/tags/?selected_tag=imagesloaded-docs). + ++ [progress with jQuery](http://codepen.io/desandro/pen/bIFyl) ++ [progress with vanilla JS](http://codepen.io/desandro/pen/hlzaw) ++ [`{ background: true }` with jQuery](http://codepen.io/desandro/pen/pjVMPB) ++ [`{ background: true }` with vanilla JS](http://codepen.io/desandro/pen/avKooW) ++ [`{ background: '.selector' }` with jQuery](http://codepen.io/desandro/pen/avKoZL) ++ [`{ background: '.selector' }` with vanilla JS](http://codepen.io/desandro/pen/vNrBGz) + +Providing a reduced test case is the best way to get your issue addressed. They help you point out the problem. They help me verify and debug the problem. They help others understand the problem. Without a reduced test case, your issue may be closed. diff --git a/vendor/desandro/imagesloaded/gulpfile.js b/vendor/desandro/imagesloaded/gulpfile.js new file mode 100644 index 000000000..66f775f3d --- /dev/null +++ b/vendor/desandro/imagesloaded/gulpfile.js @@ -0,0 +1,128 @@ +/*jshint node: true, strict: false */ + +var fs = require('fs'); +var gulp = require('gulp'); +var rename = require('gulp-rename'); +var replace = require('gulp-replace'); + +// ----- hint ----- // + +var jshint = require('gulp-jshint'); + +gulp.task( 'hint-js', function() { + return gulp.src('imagesloaded.js') + .pipe( jshint() ) + .pipe( jshint.reporter('default') ); +}); + +gulp.task( 'hint-test', function() { + return gulp.src('test/unit/*.js') + .pipe( jshint() ) + .pipe( jshint.reporter('default') ); +}); + +gulp.task( 'hint-task', function() { + return gulp.src('gulpfile.js') + .pipe( jshint() ) + .pipe( jshint.reporter('default') ); +}); + +var jsonlint = require('gulp-json-lint'); + +gulp.task( 'jsonlint', function() { + return gulp.src( '*.json' ) + .pipe( jsonlint() ) + .pipe( jsonlint.report('verbose') ); +}); + +gulp.task( 'hint', [ 'hint-js', 'hint-test', 'hint-task', 'jsonlint' ]); + +// -------------------------- RequireJS makes pkgd -------------------------- // + +// refactored from gulp-requirejs-optimize +// https://www.npmjs.com/package/gulp-requirejs-optimize/ + +var gutil = require('gulp-util'); +var chalk = require('chalk'); +var rjsOptimize = require('gulp-requirejs-optimize'); + +// regex for banner comment +var reBannerComment = new RegExp('^\\s*(?:\\/\\*[\\s\\S]*?\\*\\/)\\s*'); + +function getBanner() { + var src = fs.readFileSync( 'imagesloaded.js', 'utf8' ); + var matches = src.match( reBannerComment ); + var banner = matches[0].replace( 'imagesLoaded', 'imagesLoaded PACKAGED' ); + return banner; +} + +function addBanner( str ) { + return replace( /^/, str ); +} + +gulp.task( 'requirejs', function() { + var banner = getBanner(); + // HACK src is not needed + // should refactor rjsOptimize to produce src + return gulp.src('imagesloaded.js') + .pipe( rjsOptimize({ + baseUrl: 'bower_components', + optimize: 'none', + include: [ + '../imagesloaded' + ] + }) ) + // remove named module + .pipe( replace( "'../imagesloaded',", '' ) ) + // add banner + .pipe( addBanner( banner ) ) + .pipe( rename('imagesloaded.pkgd.js') ) + .pipe( gulp.dest('.') ); +}); + + +// ----- uglify ----- // + +var uglify = require('gulp-uglify'); + +gulp.task( 'uglify', [ 'requirejs' ], function() { + var banner = getBanner(); + gulp.src('imagesloaded.pkgd.js') + .pipe( uglify() ) + // add banner + .pipe( addBanner( banner ) ) + .pipe( rename('imagesloaded.pkgd.min.js') ) + .pipe( gulp.dest('.') ); +}); + +// ----- version ----- // + +// set version in source files + +var minimist = require('minimist'); + +// use gulp version -t 1.2.3 +gulp.task( 'version', function() { + var args = minimist( process.argv.slice(3) ); + var version = args.t; + if ( !version || !/\d+\.\d+\.\d+/.test( version ) ) { + gutil.log( 'invalid version: ' + chalk.red( version ) ); + return; + } + gutil.log( 'ticking version to ' + chalk.green( version ) ); + + gulp.src('imagesloaded.js') + .pipe( replace( /imagesLoaded v\d+\.\d+\.\d+/, 'imagesLoaded v' + version ) ) + .pipe( gulp.dest('.') ); + + gulp.src( [ 'bower.json', 'package.json' ] ) + .pipe( replace( /"version": "\d+\.\d+\.\d+"/, '"version": "' + version + '"' ) ) + .pipe( gulp.dest('.') ); +}); + +// ----- default ----- // + +gulp.task( 'default', [ + 'hint', + 'uglify' +]); diff --git a/vendor/desandro/imagesloaded/imagesloaded.js b/vendor/desandro/imagesloaded/imagesloaded.js new file mode 100644 index 000000000..f527a71e9 --- /dev/null +++ b/vendor/desandro/imagesloaded/imagesloaded.js @@ -0,0 +1,377 @@ +/*! + * imagesLoaded v4.1.4 + * JavaScript is all like "You images are done yet or what?" + * MIT License + */ + +( function( window, factory ) { 'use strict'; + // universal module definition + + /*global define: false, module: false, require: false */ + + if ( typeof define == 'function' && define.amd ) { + // AMD + define( [ + 'ev-emitter/ev-emitter' + ], function( EvEmitter ) { + return factory( window, EvEmitter ); + }); + } else if ( typeof module == 'object' && module.exports ) { + // CommonJS + module.exports = factory( + window, + require('ev-emitter') + ); + } else { + // browser global + window.imagesLoaded = factory( + window, + window.EvEmitter + ); + } + +})( typeof window !== 'undefined' ? window : this, + +// -------------------------- factory -------------------------- // + +function factory( window, EvEmitter ) { + +'use strict'; + +var $ = window.jQuery; +var console = window.console; + +// -------------------------- helpers -------------------------- // + +// extend objects +function extend( a, b ) { + for ( var prop in b ) { + a[ prop ] = b[ prop ]; + } + return a; +} + +var arraySlice = Array.prototype.slice; + +// turn element or nodeList into an array +function makeArray( obj ) { + if ( Array.isArray( obj ) ) { + // use object if already an array + return obj; + } + + var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; + if ( isArrayLike ) { + // convert nodeList to array + return arraySlice.call( obj ); + } + + // array of single index + return [ obj ]; +} + +// -------------------------- imagesLoaded -------------------------- // + +/** + * @param {Array, Element, NodeList, String} elem + * @param {Object or Function} options - if function, use as callback + * @param {Function} onAlways - callback function + */ +function ImagesLoaded( elem, options, onAlways ) { + // coerce ImagesLoaded() without new, to be new ImagesLoaded() + if ( !( this instanceof ImagesLoaded ) ) { + return new ImagesLoaded( elem, options, onAlways ); + } + // use elem as selector string + var queryElem = elem; + if ( typeof elem == 'string' ) { + queryElem = document.querySelectorAll( elem ); + } + // bail if bad element + if ( !queryElem ) { + console.error( 'Bad element for imagesLoaded ' + ( queryElem || elem ) ); + return; + } + + this.elements = makeArray( queryElem ); + this.options = extend( {}, this.options ); + // shift arguments if no options set + if ( typeof options == 'function' ) { + onAlways = options; + } else { + extend( this.options, options ); + } + + if ( onAlways ) { + this.on( 'always', onAlways ); + } + + this.getImages(); + + if ( $ ) { + // add jQuery Deferred object + this.jqDeferred = new $.Deferred(); + } + + // HACK check async to allow time to bind listeners + setTimeout( this.check.bind( this ) ); +} + +ImagesLoaded.prototype = Object.create( EvEmitter.prototype ); + +ImagesLoaded.prototype.options = {}; + +ImagesLoaded.prototype.getImages = function() { + this.images = []; + + // filter & find items if we have an item selector + this.elements.forEach( this.addElementImages, this ); +}; + +/** + * @param {Node} element + */ +ImagesLoaded.prototype.addElementImages = function( elem ) { + // filter siblings + if ( elem.nodeName == 'IMG' ) { + this.addImage( elem ); + } + // get background image on element + if ( this.options.background === true ) { + this.addElementBackgroundImages( elem ); + } + + // find children + // no non-element nodes, #143 + var nodeType = elem.nodeType; + if ( !nodeType || !elementNodeTypes[ nodeType ] ) { + return; + } + var childImgs = elem.querySelectorAll('img'); + // concat childElems to filterFound array + for ( var i=0; i < childImgs.length; i++ ) { + var img = childImgs[i]; + this.addImage( img ); + } + + // get child background images + if ( typeof this.options.background == 'string' ) { + var children = elem.querySelectorAll( this.options.background ); + for ( i=0; i < children.length; i++ ) { + var child = children[i]; + this.addElementBackgroundImages( child ); + } + } +}; + +var elementNodeTypes = { + 1: true, + 9: true, + 11: true +}; + +ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) { + var style = getComputedStyle( elem ); + if ( !style ) { + // Firefox returns null if in a hidden iframe https://bugzil.la/548397 + return; + } + // get url inside url("...") + var reURL = /url\((['"])?(.*?)\1\)/gi; + var matches = reURL.exec( style.backgroundImage ); + while ( matches !== null ) { + var url = matches && matches[2]; + if ( url ) { + this.addBackground( url, elem ); + } + matches = reURL.exec( style.backgroundImage ); + } +}; + +/** + * @param {Image} img + */ +ImagesLoaded.prototype.addImage = function( img ) { + var loadingImage = new LoadingImage( img ); + this.images.push( loadingImage ); +}; + +ImagesLoaded.prototype.addBackground = function( url, elem ) { + var background = new Background( url, elem ); + this.images.push( background ); +}; + +ImagesLoaded.prototype.check = function() { + var _this = this; + this.progressedCount = 0; + this.hasAnyBroken = false; + // complete if no images + if ( !this.images.length ) { + this.complete(); + return; + } + + function onProgress( image, elem, message ) { + // HACK - Chrome triggers event before object properties have changed. #83 + setTimeout( function() { + _this.progress( image, elem, message ); + }); + } + + this.images.forEach( function( loadingImage ) { + loadingImage.once( 'progress', onProgress ); + loadingImage.check(); + }); +}; + +ImagesLoaded.prototype.progress = function( image, elem, message ) { + this.progressedCount++; + this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; + // progress event + this.emitEvent( 'progress', [ this, image, elem ] ); + if ( this.jqDeferred && this.jqDeferred.notify ) { + this.jqDeferred.notify( this, image ); + } + // check if completed + if ( this.progressedCount == this.images.length ) { + this.complete(); + } + + if ( this.options.debug && console ) { + console.log( 'progress: ' + message, image, elem ); + } +}; + +ImagesLoaded.prototype.complete = function() { + var eventName = this.hasAnyBroken ? 'fail' : 'done'; + this.isComplete = true; + this.emitEvent( eventName, [ this ] ); + this.emitEvent( 'always', [ this ] ); + if ( this.jqDeferred ) { + var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve'; + this.jqDeferred[ jqMethod ]( this ); + } +}; + +// -------------------------- -------------------------- // + +function LoadingImage( img ) { + this.img = img; +} + +LoadingImage.prototype = Object.create( EvEmitter.prototype ); + +LoadingImage.prototype.check = function() { + // If complete is true and browser supports natural sizes, + // try to check for image status manually. + var isComplete = this.getIsImageComplete(); + if ( isComplete ) { + // report based on naturalWidth + this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); + return; + } + + // If none of the checks above matched, simulate loading on detached element. + this.proxyImage = new Image(); + this.proxyImage.addEventListener( 'load', this ); + this.proxyImage.addEventListener( 'error', this ); + // bind to image as well for Firefox. #191 + this.img.addEventListener( 'load', this ); + this.img.addEventListener( 'error', this ); + this.proxyImage.src = this.img.src; +}; + +LoadingImage.prototype.getIsImageComplete = function() { + // check for non-zero, non-undefined naturalWidth + // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671 + return this.img.complete && this.img.naturalWidth; +}; + +LoadingImage.prototype.confirm = function( isLoaded, message ) { + this.isLoaded = isLoaded; + this.emitEvent( 'progress', [ this, this.img, message ] ); +}; + +// ----- events ----- // + +// trigger specified handler for event type +LoadingImage.prototype.handleEvent = function( event ) { + var method = 'on' + event.type; + if ( this[ method ] ) { + this[ method ]( event ); + } +}; + +LoadingImage.prototype.onload = function() { + this.confirm( true, 'onload' ); + this.unbindEvents(); +}; + +LoadingImage.prototype.onerror = function() { + this.confirm( false, 'onerror' ); + this.unbindEvents(); +}; + +LoadingImage.prototype.unbindEvents = function() { + this.proxyImage.removeEventListener( 'load', this ); + this.proxyImage.removeEventListener( 'error', this ); + this.img.removeEventListener( 'load', this ); + this.img.removeEventListener( 'error', this ); +}; + +// -------------------------- Background -------------------------- // + +function Background( url, element ) { + this.url = url; + this.element = element; + this.img = new Image(); +} + +// inherit LoadingImage prototype +Background.prototype = Object.create( LoadingImage.prototype ); + +Background.prototype.check = function() { + this.img.addEventListener( 'load', this ); + this.img.addEventListener( 'error', this ); + this.img.src = this.url; + // check if image is already complete + var isComplete = this.getIsImageComplete(); + if ( isComplete ) { + this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); + this.unbindEvents(); + } +}; + +Background.prototype.unbindEvents = function() { + this.img.removeEventListener( 'load', this ); + this.img.removeEventListener( 'error', this ); +}; + +Background.prototype.confirm = function( isLoaded, message ) { + this.isLoaded = isLoaded; + this.emitEvent( 'progress', [ this, this.element, message ] ); +}; + +// -------------------------- jQuery -------------------------- // + +ImagesLoaded.makeJQueryPlugin = function( jQuery ) { + jQuery = jQuery || window.jQuery; + if ( !jQuery ) { + return; + } + // set local variable + $ = jQuery; + // $().imagesLoaded() + $.fn.imagesLoaded = function( options, callback ) { + var instance = new ImagesLoaded( this, options, callback ); + return instance.jqDeferred.promise( $(this) ); + }; +}; +// try making plugin +ImagesLoaded.makeJQueryPlugin(); + +// -------------------------- -------------------------- // + +return ImagesLoaded; + +}); diff --git a/library/imagesloaded/imagesloaded.pkgd.js b/vendor/desandro/imagesloaded/imagesloaded.pkgd.js similarity index 89% rename from library/imagesloaded/imagesloaded.pkgd.js rename to vendor/desandro/imagesloaded/imagesloaded.pkgd.js index ef23971be..a230750b3 100644 --- a/library/imagesloaded/imagesloaded.pkgd.js +++ b/vendor/desandro/imagesloaded/imagesloaded.pkgd.js @@ -1,11 +1,11 @@ /*! - * imagesLoaded PACKAGED v4.1.0 + * imagesLoaded PACKAGED v4.1.4 * JavaScript is all like "You images are done yet or what?" * MIT License */ /** - * EvEmitter v1.0.1 + * EvEmitter v1.1.0 * Lil' event emitter * MIT License */ @@ -14,7 +14,7 @@ ( function( global, factory ) { // universal module definition - /* jshint strict: false */ /* globals define, module */ + /* jshint strict: false */ /* globals define, module, window */ if ( typeof define == 'function' && define.amd ) { // AMD - RequireJS define( 'ev-emitter/ev-emitter',factory ); @@ -26,7 +26,7 @@ global.EvEmitter = factory(); } -}( this, function() { +}( typeof window != 'undefined' ? window : this, function() { @@ -59,8 +59,8 @@ proto.once = function( eventName, listener ) { // set once flag // set onceEvents hash var onceEvents = this._onceEvents = this._onceEvents || {}; - // set onceListeners array - var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || []; + // set onceListeners object + var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; // set flag onceListeners[ listener ] = true; @@ -85,13 +85,14 @@ proto.emitEvent = function( eventName, args ) { if ( !listeners || !listeners.length ) { return; } - var i = 0; - var listener = listeners[i]; + // copy over to avoid interference if .off() in listener + listeners = listeners.slice(0); args = args || []; // once stuff var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; - while ( listener ) { + for ( var i=0; i < listeners.length; i++ ) { + var listener = listeners[i] var isOnce = onceListeners && onceListeners[ listener ]; if ( isOnce ) { // remove listener @@ -102,20 +103,22 @@ proto.emitEvent = function( eventName, args ) { } // trigger listener listener.apply( this, args ); - // get next listener - i += isOnce ? 0 : 1; - listener = listeners[i]; } return this; }; +proto.allOff = function() { + delete this._events; + delete this._onceEvents; +}; + return EvEmitter; })); /*! - * imagesLoaded v4.1.0 + * imagesLoaded v4.1.4 * JavaScript is all like "You images are done yet or what?" * MIT License */ @@ -146,7 +149,7 @@ return EvEmitter; ); } -})( window, +})( typeof window !== 'undefined' ? window : this, // -------------------------- factory -------------------------- // @@ -167,22 +170,23 @@ function extend( a, b ) { return a; } +var arraySlice = Array.prototype.slice; + // turn element or nodeList into an array function makeArray( obj ) { - var ary = []; if ( Array.isArray( obj ) ) { // use object if already an array - ary = obj; - } else if ( typeof obj.length == 'number' ) { - // convert nodeList to array - for ( var i=0; i < obj.length; i++ ) { - ary.push( obj[i] ); - } - } else { - // array of single index - ary.push( obj ); + return obj; } - return ary; + + var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; + if ( isArrayLike ) { + // convert nodeList to array + return arraySlice.call( obj ); + } + + // array of single index + return [ obj ]; } // -------------------------- imagesLoaded -------------------------- // @@ -198,13 +202,19 @@ function ImagesLoaded( elem, options, onAlways ) { return new ImagesLoaded( elem, options, onAlways ); } // use elem as selector string + var queryElem = elem; if ( typeof elem == 'string' ) { - elem = document.querySelectorAll( elem ); + queryElem = document.querySelectorAll( elem ); + } + // bail if bad element + if ( !queryElem ) { + console.error( 'Bad element for imagesLoaded ' + ( queryElem || elem ) ); + return; } - this.elements = makeArray( elem ); + this.elements = makeArray( queryElem ); this.options = extend( {}, this.options ); - + // shift arguments if no options set if ( typeof options == 'function' ) { onAlways = options; } else { @@ -223,9 +233,7 @@ function ImagesLoaded( elem, options, onAlways ) { } // HACK check async to allow time to bind listeners - setTimeout( function() { - this.check(); - }.bind( this )); + setTimeout( this.check.bind( this ) ); } ImagesLoaded.prototype = Object.create( EvEmitter.prototype ); @@ -393,7 +401,9 @@ LoadingImage.prototype.check = function() { }; LoadingImage.prototype.getIsImageComplete = function() { - return this.img.complete && this.img.naturalWidth !== undefined; + // check for non-zero, non-undefined naturalWidth + // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671 + return this.img.complete && this.img.naturalWidth; }; LoadingImage.prototype.confirm = function( isLoaded, message ) { diff --git a/vendor/desandro/imagesloaded/imagesloaded.pkgd.min.js b/vendor/desandro/imagesloaded/imagesloaded.pkgd.min.js new file mode 100644 index 000000000..e443a77d6 --- /dev/null +++ b/vendor/desandro/imagesloaded/imagesloaded.pkgd.min.js @@ -0,0 +1,7 @@ +/*! + * imagesLoaded PACKAGED v4.1.4 + * JavaScript is all like "You images are done yet or what?" + * MIT License + */ + +!function(e,t){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",t):"object"==typeof module&&module.exports?module.exports=t():e.EvEmitter=t()}("undefined"!=typeof window?window:this,function(){function e(){}var t=e.prototype;return t.on=function(e,t){if(e&&t){var i=this._events=this._events||{},n=i[e]=i[e]||[];return n.indexOf(t)==-1&&n.push(t),this}},t.once=function(e,t){if(e&&t){this.on(e,t);var i=this._onceEvents=this._onceEvents||{},n=i[e]=i[e]||{};return n[t]=!0,this}},t.off=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){var n=i.indexOf(t);return n!=-1&&i.splice(n,1),this}},t.emitEvent=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){i=i.slice(0),t=t||[];for(var n=this._onceEvents&&this._onceEvents[e],o=0;o + + + + + + background + + + + + + + +

background

+ +
+ +
+ +
+ +
+ + + + + + + diff --git a/vendor/desandro/imagesloaded/sandbox/progress/index.html b/vendor/desandro/imagesloaded/sandbox/progress/index.html new file mode 100644 index 000000000..b01ce28c5 --- /dev/null +++ b/vendor/desandro/imagesloaded/sandbox/progress/index.html @@ -0,0 +1,89 @@ + + + + + + + progress + + + + + + +

progress

+ +
+ + +
+
+ +
+
+ + + + + + + diff --git a/vendor/desandro/imagesloaded/sandbox/progress/progress.js b/vendor/desandro/imagesloaded/sandbox/progress/progress.js new file mode 100644 index 000000000..7c00003f5 --- /dev/null +++ b/vendor/desandro/imagesloaded/sandbox/progress/progress.js @@ -0,0 +1,111 @@ +/* jshint strict: false */ + +var progressElem, statusElem; +var supportsProgress; +var loadedImageCount, imageCount; + +var container = document.querySelector('#image-container'); +statusElem = document.querySelector('#status'); +progressElem = document.querySelector('progress'); + +supportsProgress = progressElem && + // IE does not support progress + progressElem.toString().indexOf('Unknown') === -1; + +document.querySelector('#add').onclick = function() { + // add new images + var fragment = getItemsFragment(); + container.insertBefore( fragment, container.firstChild ); + // use ImagesLoaded + var imgLoad = imagesLoaded( container ); + imgLoad.on( 'progress', onProgress ); + imgLoad.on( 'always', onAlways ); + // reset progress counter + imageCount = imgLoad.images.length; + resetProgress(); + updateProgress( 0 ); +}; + +// reset container +document.querySelector('#reset').onclick = function() { + empty( container ); +}; + +// ----- set text helper ----- // + +var docElem = document.documentElement; +var textSetter = docElem.textContent !== undefined ? 'textContent' : 'innerText'; + +function setText( elem, value ) { + elem[ textSetter ] = value; +} + +function empty( elem ) { + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } +} + +// ----- ----- // + +// return doc fragment with +function getItemsFragment() { + var fragment = document.createDocumentFragment(); + for ( var i = 0; i < 7; i++ ) { + var item = getImageItem(); + fragment.appendChild( item ); + } + return fragment; +} + +// return an
  • with a in it +function getImageItem() { + var item = document.createElement('li'); + item.className = 'is-loading'; + var img = document.createElement('img'); + var size = Math.random() * 3 + 1; + var width = Math.random() * 110 + 100; + width = Math.round( width * size ); + var height = Math.round( 140 * size ); + var rando = Math.ceil( Math.random() * 1000 ); + // 10% chance of broken image src + // random parameter to prevent cached images + img.src = rando < 100 ? '//foo/broken-' + rando + '.jpg' : + // use picsum for great random images + 'https://picsum.photos/' + width + '/' + height + '/' + '?random'; + item.appendChild( img ); + return item; +} + +// ----- ----- // + +function resetProgress() { + statusElem.style.opacity = 1; + loadedImageCount = 0; + if ( supportsProgress ) { + progressElem.setAttribute( 'max', imageCount ); + } +} + +function updateProgress( value ) { + if ( supportsProgress ) { + progressElem.setAttribute( 'value', value ); + } else { + // if you don't support progress elem + setText( statusElem, value + ' / ' + imageCount ); + } +} + +// triggered after each item is loaded +function onProgress( imgLoad, image ) { + // change class if the image is loaded or broken + image.img.parentNode.className = image.isLoaded ? '' : 'is-broken'; + // update progress element + loadedImageCount++; + updateProgress( loadedImageCount ); +} + +// hide status when done +function onAlways() { + statusElem.style.opacity = 0; +} diff --git a/vendor/desandro/imagesloaded/test/css/tests.css b/vendor/desandro/imagesloaded/test/css/tests.css new file mode 100644 index 000000000..af8a7e885 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/css/tests.css @@ -0,0 +1,41 @@ +img { + display: inline-block; + max-width: 240px; +} + +/* ---- backgrounds ---- */ + +.bg-box { + width: 240px; + height: 240px; + margin: 0 20px 20px 0; + border: 1px solid; + display: inline-block; +} + +.bg-box.tulip { + background: url('http://i.imgur.com/9xYjgCk.jpg'); + background-size: cover; +} + +.bg-box.thunder-cloud { + background: url('../img/thunder-cloud.jpg'); + background-size: contain; +} + +.bg-box.multi { + background: + url("http://i.imgur.com/ZAVN3.png"), + url('http://i.imgur.com/6UdOxeB.png') bottom right, + url(https://picsum.photos/601/401/?random); + background-size: cover; +} + +.bg-box.blue { + background: #09F; +} + +.bg-box.gulls { + background-image: url('http://i.imgur.com/qKhkOKC.jpg'); + background-size: cover; +} diff --git a/vendor/desandro/imagesloaded/test/img/blue-shell.jpg b/vendor/desandro/imagesloaded/test/img/blue-shell.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b47f1e9270e7afd06d9a1d02afb243cd3cda2468 GIT binary patch literal 24555 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 I#9wp&20mn!hX4Qo literal 0 HcmV?d00001 diff --git a/vendor/desandro/imagesloaded/test/img/bowser-jr.jpg b/vendor/desandro/imagesloaded/test/img/bowser-jr.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b1de2a76f76268f079e491c171bcdbecd5968143 GIT binary patch literal 36987 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 literal 0 HcmV?d00001 diff --git a/vendor/desandro/imagesloaded/test/img/thunder-cloud.jpg b/vendor/desandro/imagesloaded/test/img/thunder-cloud.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54fc9a1b74498641586875285c94c6c90a5561af GIT binary patch literal 24588 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 literal 0 HcmV?d00001 diff --git a/vendor/desandro/imagesloaded/test/index.html b/vendor/desandro/imagesloaded/test/index.html new file mode 100644 index 000000000..02b04f4a6 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/index.html @@ -0,0 +1,104 @@ + + + + + + imagesLoaded tests + + + + + + + + + + + + + + + + + + + + + + + + + +

    imagesLoaded tests

    + +
    + +

    Basics

    + +
    + + + + + +
    + + + +

    Locals

    + +
    + + + + +
    + +

    Data URI

    + +
    + + +
    + +

    append

    + +
    + +

    no images

    + +
    + +

    jQuery success

    + +
    + + + +
    + +

    jQuery fail

    + +
    + + + + + +
    + +

    background

    + +
    +
    +
    +
    +
    +
    + + +
    +
    + + + diff --git a/vendor/desandro/imagesloaded/test/unit/append.js b/vendor/desandro/imagesloaded/test/unit/append.js new file mode 100644 index 000000000..7a6b3c827 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/append.js @@ -0,0 +1,30 @@ +QUnit.test( 'append', function( assert ) { + 'use strict'; + + var imgUrls = [ + 'http://i.imgur.com/bwy74ok.jpg', + 'http://i.imgur.com/bAZWoqx.jpg', + 'http://i.imgur.com/PgmEBSB.jpg', + 'http://i.imgur.com/aboaFoB.jpg', + 'http://i.imgur.com/LkmcILl.jpg', + 'http://i.imgur.com/q9zO6tw.jpg' + ]; + + // create images + var fragment = document.createDocumentFragment(); + for ( var i=0, len = imgUrls.length; i < len; i++ ) { + var img = document.createElement('img'); + img.src = imgUrls[i]; + fragment.appendChild( img ); + } + + var elem = document.querySelector('#append'); + elem.appendChild( fragment ); + var done = assert.async(); + + imagesLoaded( elem, { debug: false } ).on( 'always', function() { + assert.ok( 'appended images loaded' ); + done(); + }); + +}); diff --git a/vendor/desandro/imagesloaded/test/unit/background.js b/vendor/desandro/imagesloaded/test/unit/background.js new file mode 100644 index 000000000..ca76fad6f --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/background.js @@ -0,0 +1,70 @@ +QUnit.test( 'background', function( assert ) { + 'use strict'; + + // from Modernizr + var supportsMultiBGs = ( function() { + var style = document.createElement('a').style; + style.cssText = 'background:url(https://),url(https://),red url(https://)'; + return (/(url\s*\(.*?){3}/).test(style.background); + })(); + + var multiBGCount = supportsMultiBGs ? 3 : 0; + var done = assert.async( 14 + multiBGCount ); + + var imgLoad0 = imagesLoaded( '#background .tulip', { background: true }, function() { + assert.ok( true, 'callback triggered on .orange-tree'); + done(); + }); + assert.equal( imgLoad0.images.length, 1, '1 image on .images' ); + + imgLoad0.on( 'progress', function( instance, image, element ) { + assert.ok( element.nodeName == 'DIV', 'progress; element is div'); + assert.ok( image.isLoaded, 'progress; image.isLoaded'); + done(); + }); + + var imgLoad1 = imagesLoaded( '#background .thunder-cloud', { background: true }, function() { + assert.ok( true, 'callback triggered on .thunder-cloud'); + done(); + }); + assert.equal( imgLoad1.images.length, 1, '1 image on .images' ); + + // multiple backgrounds + var imgLoad2 = imagesLoaded( '#background .multi', { background: true }, function() { + assert.ok( true, 'callback triggered on .multi'); + done(); + }); + assert.equal( imgLoad2.images.length, multiBGCount, 'correct multiple BG count on .images' ); + + // multiple elements + var imgLoad3 = imagesLoaded( '#background .bg-box', { background: true }, function() { + assert.ok( true, 'callback triggered on .bg-box'); + var count = 5 + multiBGCount; + assert.equal( imgLoad3.images.length, count, count + ' images on .bg-box' ); + done(); + }); + + imgLoad3.on('progress', function( instance, image/*, element */) { + assert.ok( true, 'progress on .bg-box; ' + image.img.src ); + assert.equal( image.isLoaded, true, 'image.isLoaded == true' ); + done(); + }); + + // background and children + var imgLoad4 = imagesLoaded( '#background .gulls', { background: true } ); + assert.equal( imgLoad4.images.length, 3, '3 images: 1 background and 2 ' ); + + imgLoad4.on( 'progress', function( instance, image ) { + assert.equal( image.isLoaded, true, 'image is loaded' ); + done(); + }); + + // child background selector + var imgLoad5 = imagesLoaded( '#background', { background: '.bg-box' }, function() { + var count = 5 + multiBGCount; + assert.equal( imgLoad5.images.length, count, + count + ' images on .bg-box, with {background: .bg-box}' ); + done(); + }); + +}); diff --git a/vendor/desandro/imagesloaded/test/unit/basics.js b/vendor/desandro/imagesloaded/test/unit/basics.js new file mode 100644 index 000000000..6c502a793 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/basics.js @@ -0,0 +1,28 @@ +QUnit.test( 'basics', function( assert ) { + + 'use strict'; + + var elem = document.querySelector('#basics'); + var images = elem.querySelectorAll('img'); + var done = assert.async( 3 + images.length ); + + var imgLoader = new imagesLoaded( elem, function( obj ) { + assert.ok( true, 'callback function triggered' ); + assert.equal( imgLoader, obj, 'callback argument and instance match' ); + done(); + }); + imgLoader.on( 'done', function() { + assert.ok( true, 'done event triggered' ); + done(); + }); + imgLoader.on( 'always', function() { + assert.ok( true, 'always event triggered' ); + done(); + }); + + imgLoader.on( 'progress', function( loader, image ) { + assert.ok( image.isLoaded, 'image is loaded'); + done(); + }); + +}); diff --git a/vendor/desandro/imagesloaded/test/unit/data-uri.js b/vendor/desandro/imagesloaded/test/unit/data-uri.js new file mode 100644 index 000000000..635f69859 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/data-uri.js @@ -0,0 +1,10 @@ +QUnit.test( 'data-uri', function( assert ) { + 'use strict'; + + var done = assert.async(); + imagesLoaded('#data-uri', { debug: false }).on( 'done', function( obj ) { + assert.ok( true, 'data-uri images loaded' ); + assert.equal( obj.images.length, 2, 'instance has 2 images' ); + done(); + }); +}); diff --git a/vendor/desandro/imagesloaded/test/unit/jquery-fail.js b/vendor/desandro/imagesloaded/test/unit/jquery-fail.js new file mode 100644 index 000000000..b2180f6f2 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/jquery-fail.js @@ -0,0 +1,29 @@ +QUnit.test( 'jquery fail', function( assert ) { + + 'use strict'; + + var $ = window.jQuery; + var $images = $('#jquery-fail img'); + var done = assert.async( 3 + $images.length ); + + $('#jquery-fail').imagesLoaded( function( instance ) { + assert.ok( true, 'callback triggered' ); + assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' ); + done(); + }) + .fail( function( instance ) { + assert.ok( true, 'fail triggered' ); + assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' ); + done(); + }) + .always( function( instance ) { + assert.ok( true, 'always triggered' ); + assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' ); + done(); + }) + .progress( function(/* instance, image */) { + assert.ok( true, 'progress trigged'); + done(); + }); + + }); diff --git a/vendor/desandro/imagesloaded/test/unit/jquery-success.js b/vendor/desandro/imagesloaded/test/unit/jquery-success.js new file mode 100644 index 000000000..f16621088 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/jquery-success.js @@ -0,0 +1,28 @@ +QUnit.test( 'jquery success', function( assert ) { + + 'use strict'; + + var $ = window.jQuery; + var done = assert.async( 6 ); + + $('#jquery-success').imagesLoaded( function( instance ) { + assert.ok( true, 'callback triggered' ); + assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' ); + done(); + }) + .done( function( instance ) { + assert.ok( true, 'done triggered' ); + assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' ); + done(); + }) + .always( function( instance ) { + assert.ok( true, 'always triggered' ); + assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' ); + done(); + }) + .progress( function( instance, image ) { + assert.ok( image.isLoaded, 'progress trigged, image is loaded'); + done(); + }); + +}); diff --git a/vendor/desandro/imagesloaded/test/unit/local-files.js b/vendor/desandro/imagesloaded/test/unit/local-files.js new file mode 100644 index 000000000..61da6ae92 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/local-files.js @@ -0,0 +1,31 @@ +QUnit.test( 'local files', function( assert ) { + 'use strict'; + + var elem = document.querySelector('#locals'); + var done = assert.async( 6 ); + + var imgLoader = new imagesLoaded( elem, function( obj ) { + assert.ok( true, 'callback function triggered' ); + assert.equal( imgLoader, obj, 'callback argument and instance match' ); + done(); + }); + imgLoader.on( 'fail', function() { + assert.ok( true, 'fail event triggered' ); + done(); + }); + imgLoader.on( 'always', function() { + assert.ok( true, 'always event triggered' ); + done(); + }); + + imgLoader.on( 'progress', function( loader, image ) { + assert.ok( true, 'image progressed'); + if ( image.img.src.indexOf('img/not-there.jpg') !== -1 ) { + assert.ok( !image.isLoaded, 'thunder cloud is not loaded' ); + } else { + assert.ok( image.isLoaded, 'image is loaded' ); + } + done(); + }); + +}); diff --git a/vendor/desandro/imagesloaded/test/unit/no-images.js b/vendor/desandro/imagesloaded/test/unit/no-images.js new file mode 100644 index 000000000..841216381 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/no-images.js @@ -0,0 +1,11 @@ +QUnit.test( 'no images', function( assert ) { + 'use strict'; + + var elem = document.querySelector('#no-images'); + var done = assert.async(); + imagesLoaded( elem, function() { + assert.ok( true, 'triggered with no images' ); + done(); + }); + +}); diff --git a/vendor/desandro/imagesloaded/test/unit/non-element.js b/vendor/desandro/imagesloaded/test/unit/non-element.js new file mode 100644 index 000000000..4c9986fa6 --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/non-element.js @@ -0,0 +1,24 @@ +QUnit.test( 'dismiss non-element nodes', function( assert ) { + 'use strict'; + + var $ = window.jQuery; + var done = assert.async( 2 ); + + $(' ') + .imagesLoaded(function() { + assert.ok( true, 'elements from jQuery string ok' ); + done(); + }); + + // test fragment + var frag = document.createDocumentFragment(); + var img = new Image(); + img.src = 'https://picsum.photos/403/303/?random'; + frag.appendChild( img ); + var imgLoad = imagesLoaded( frag, function() { + assert.ok( true, 'document fragment ok' ); + assert.equal( imgLoad.images.length, 1, '1 image found' ); + done(); + }); + +}); diff --git a/vendor/desandro/imagesloaded/test/unit/selector-string.js b/vendor/desandro/imagesloaded/test/unit/selector-string.js new file mode 100644 index 000000000..8c43c4bef --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/selector-string.js @@ -0,0 +1,12 @@ +QUnit.test( 'selector string', function( assert ) { + 'use strict'; + var images = document.querySelectorAll('#basics img'); + var done = assert.async(); + var imgLoad = imagesLoaded('#basics', { debug: true }).on( 'done', function( obj ) { + assert.ok( true, 'selector string worked' ); + assert.ok( obj.images, 'argument has images' ); + assert.equal( obj.images.length, images.length, 'images.length matches' ); + done(); + }); + assert.ok( imgLoad.options.debug, 'debug option set' ); +}); diff --git a/vendor/desandro/imagesloaded/test/unit/single-element.js b/vendor/desandro/imagesloaded/test/unit/single-element.js new file mode 100644 index 000000000..42d7e48ee --- /dev/null +++ b/vendor/desandro/imagesloaded/test/unit/single-element.js @@ -0,0 +1,11 @@ +QUnit.test( 'single element', function( assert ) { + 'use strict'; + var elem = document.querySelector('#mario-with-shell'); + var done = assert.async(); + imagesLoaded( elem ).on( 'done', function( obj ) { + assert.ok( true, 'single element worked' ); + assert.ok( obj.images, 'argument has images' ); + assert.equal( obj.images.length, 1, 'images.length = 1' ); + done(); + }); +}); diff --git a/view/php/theme_init.php b/view/php/theme_init.php index dd8dcb5ee..73e559c45 100644 --- a/view/php/theme_init.php +++ b/view/php/theme_init.php @@ -36,7 +36,7 @@ head_add_js('/library/colorbox/jquery.colorbox-min.js'); head_add_js('/library/jquery.AreYouSure/jquery.are-you-sure.js'); head_add_js('/library/tableofcontents/jquery.toc.js'); -head_add_js('/library/imagesloaded/imagesloaded.pkgd.min.js'); +head_add_js('/vendor/desandro/imagesloaded/imagesloaded.pkgd.min.js'); /** * Those who require this feature will know what to do with it. * Those who don't, won't. From a151532ffaf55fa1bc0017d9a83cd21c2f885828 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 25 Nov 2018 09:18:26 +0000 Subject: [PATCH 06/24] update jquery-file-upload and psr-log via composer (cherry picked from commit c7ae3fdc9af6e78ddee63fff4a9938df27d0d39d) --- composer.lock | 130 +++++++++--------- vendor/blueimp/jquery-file-upload/README.md | 2 +- vendor/blueimp/jquery-file-upload/SECURITY.md | 2 +- .../blueimp/jquery-file-upload/angularjs.html | 8 +- .../jquery-file-upload/basic-plus.html | 8 +- vendor/blueimp/jquery-file-upload/basic.html | 6 +- .../bower-version-update.js | 0 vendor/blueimp/jquery-file-upload/bower.json | 2 +- .../jquery-file-upload/cors/postmessage.html | 2 +- vendor/blueimp/jquery-file-upload/index.html | 6 +- .../blueimp/jquery-file-upload/jquery-ui.html | 6 +- .../blueimp/jquery-file-upload/package.json | 2 +- .../server/php/UploadHandler.php | 34 +++-- .../jquery-file-upload/server/php/index.php | 2 +- .../jquery-file-upload/test/index.html | 6 +- vendor/composer/autoload_classmap.php | 3 + vendor/composer/autoload_static.php | 3 + vendor/composer/installed.json | 28 ++-- vendor/psr/log/README.md | 7 + 19 files changed, 139 insertions(+), 118 deletions(-) mode change 100755 => 100644 vendor/blueimp/jquery-file-upload/bower-version-update.js mode change 100755 => 100644 vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php diff --git a/composer.lock b/composer.lock index 64d28c22e..bd95e8c78 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "blueimp/jquery-file-upload", - "version": "v9.25.1", + "version": "v9.28.0", "source": { "type": "git", "url": "https://github.com/vkhramtsov/jQuery-File-Upload.git", - "reference": "28891f9b2bc339bcc1ca8d548e5401e8563bf04b" + "reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/28891f9b2bc339bcc1ca8d548e5401e8563bf04b", - "reference": "28891f9b2bc339bcc1ca8d548e5401e8563bf04b", + "url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/ff5accfe2e5c4a522777faa980a90cf86a636d1d", + "reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d", "shasum": "" }, "type": "library", @@ -59,7 +59,7 @@ "upload", "widget" ], - "time": "2018-10-26T07:21:48+00:00" + "time": "2018-11-13T05:41:39+00:00" }, { "name": "bshaffer/oauth2-server-php", @@ -485,16 +485,16 @@ }, { "name": "psr/log", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", "shasum": "" }, "require": { @@ -528,7 +528,7 @@ "psr", "psr-3" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2018-11-20T15:27:04+00:00" }, { "name": "ramsey/uuid", @@ -1149,7 +1149,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.9.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -2575,16 +2575,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "6.1.3", + "version": "6.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "4d3ae9b21a7d7e440bd0cf65565533117976859f" + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4d3ae9b21a7d7e440bd0cf65565533117976859f", - "reference": "4d3ae9b21a7d7e440bd0cf65565533117976859f", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", "shasum": "" }, "require": { @@ -2634,7 +2634,7 @@ "testing", "xunit" ], - "time": "2018-10-23T05:59:32+00:00" + "time": "2018-10-31T16:06:48+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2827,16 +2827,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.4.3", + "version": "7.4.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c151651fb6ed264038d486ea262e243af72e5e64" + "reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c151651fb6ed264038d486ea262e243af72e5e64", - "reference": "c151651fb6ed264038d486ea262e243af72e5e64", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b1be2c8530c4c29c3519a052c9fb6cee55053bbd", + "reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd", "shasum": "" }, "require": { @@ -2907,7 +2907,7 @@ "testing", "xunit" ], - "time": "2018-10-23T05:57:41+00:00" + "time": "2018-11-14T16:52:02+00:00" }, { "name": "psr/container", @@ -3573,7 +3573,7 @@ }, { "name": "symfony/browser-kit", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", @@ -3630,16 +3630,16 @@ }, { "name": "symfony/class-loader", - "version": "v3.4.17", + "version": "v3.4.18", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", - "reference": "f31333bdff54c7595f834d510a6d2325573ddb36" + "reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/f31333bdff54c7595f834d510a6d2325573ddb36", - "reference": "f31333bdff54c7595f834d510a6d2325573ddb36", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/5605edec7b8f034ead2497ff4aab17bb70d558c1", + "reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1", "shasum": "" }, "require": { @@ -3682,20 +3682,20 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2018-10-02T12:28:39+00:00" + "time": "2018-10-31T09:06:03+00:00" }, { "name": "symfony/config", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "b3d4d7b567d7a49e6dfafb6d4760abc921177c96" + "reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/b3d4d7b567d7a49e6dfafb6d4760abc921177c96", - "reference": "b3d4d7b567d7a49e6dfafb6d4760abc921177c96", + "url": "https://api.github.com/repos/symfony/config/zipball/991fec8bbe77367fc8b48ecbaa8a4bd6e905a238", + "reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238", "shasum": "" }, "require": { @@ -3745,20 +3745,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2018-09-08T13:24:10+00:00" + "time": "2018-10-31T09:09:42+00:00" }, { "name": "symfony/console", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "dc7122fe5f6113cfaba3b3de575d31112c9aa60b" + "reference": "432122af37d8cd52fba1b294b11976e0d20df595" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/dc7122fe5f6113cfaba3b3de575d31112c9aa60b", - "reference": "dc7122fe5f6113cfaba3b3de575d31112c9aa60b", + "url": "https://api.github.com/repos/symfony/console/zipball/432122af37d8cd52fba1b294b11976e0d20df595", + "reference": "432122af37d8cd52fba1b294b11976e0d20df595", "shasum": "" }, "require": { @@ -3813,11 +3813,11 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-10-03T08:15:46+00:00" + "time": "2018-10-31T09:30:44+00:00" }, { "name": "symfony/css-selector", - "version": "v3.4.17", + "version": "v3.4.18", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -3870,16 +3870,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f6b9d893ad28aefd8942dc0469c8397e2216fe30" + "reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f6b9d893ad28aefd8942dc0469c8397e2216fe30", - "reference": "f6b9d893ad28aefd8942dc0469c8397e2216fe30", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e72ee2c23d952e4c368ee98610fa22b79b89b483", + "reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483", "shasum": "" }, "require": { @@ -3937,11 +3937,11 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2018-10-02T12:40:59+00:00" + "time": "2018-10-31T10:54:16+00:00" }, { "name": "symfony/dom-crawler", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", @@ -3998,16 +3998,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "bfb30c2ad377615a463ebbc875eba64a99f6aa3e" + "reference": "552541dad078c85d9414b09c041ede488b456cd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bfb30c2ad377615a463ebbc875eba64a99f6aa3e", - "reference": "bfb30c2ad377615a463ebbc875eba64a99f6aa3e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/552541dad078c85d9414b09c041ede488b456cd5", + "reference": "552541dad078c85d9414b09c041ede488b456cd5", "shasum": "" }, "require": { @@ -4057,20 +4057,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-07-26T09:10:45+00:00" + "time": "2018-10-10T13:52:42+00:00" }, { "name": "symfony/filesystem", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "596d12b40624055c300c8b619755b748ca5cf0b5" + "reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/596d12b40624055c300c8b619755b748ca5cf0b5", - "reference": "596d12b40624055c300c8b619755b748ca5cf0b5", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd7bd6535beb1f0a0a9e3ee960666d0598546981", + "reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981", "shasum": "" }, "require": { @@ -4107,20 +4107,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-10-02T12:40:59+00:00" + "time": "2018-10-30T13:18:25+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.9.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8" + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8", - "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", "shasum": "" }, "require": { @@ -4166,20 +4166,20 @@ "portable", "shim" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2018-09-21T13:07:52+00:00" }, { "name": "symfony/translation", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "9f0b61e339160a466ebcde167a6c5521c810e304" + "reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/9f0b61e339160a466ebcde167a6c5521c810e304", - "reference": "9f0b61e339160a466ebcde167a6c5521c810e304", + "url": "https://api.github.com/repos/symfony/translation/zipball/aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c", + "reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c", "shasum": "" }, "require": { @@ -4235,11 +4235,11 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:36:10+00:00" + "time": "2018-10-28T18:38:52+00:00" }, { "name": "symfony/yaml", - "version": "v4.1.6", + "version": "v4.1.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", diff --git a/vendor/blueimp/jquery-file-upload/README.md b/vendor/blueimp/jquery-file-upload/README.md index d2f104d5c..d9e16ed18 100644 --- a/vendor/blueimp/jquery-file-upload/README.md +++ b/vendor/blueimp/jquery-file-upload/README.md @@ -10,7 +10,7 @@ Supports cross-domain, chunked and resumable file uploads and client-side image ## ⚠️ Security Notice Security related releases: -* [v9.25.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.25.1) Mitigates some [Potential vulnerabilities with PHP+ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php+imagemagick). +* [v9.25.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.25.1) Mitigates some [Potential vulnerabilities with PHP+ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php-imagemagick). * [v9.24.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.24.1) Fixes a [Remote code execution vulnerability in the PHP component](VULNERABILITIES.md#remote-code-execution-vulnerability-in-the-php-component). * v[9.10.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/9.10.1) Fixes an [Open redirect vulnerability in the GAE components](VULNERABILITIES.md#open-redirect-vulnerability-in-the-gae-components). * Commit [4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a) (*fixed in all tagged releases*) Fixes a [Cross-site scripting vulnerability in the Iframe Transport](VULNERABILITIES.md#cross-site-scripting-vulnerability-in-the-iframe-transport). diff --git a/vendor/blueimp/jquery-file-upload/SECURITY.md b/vendor/blueimp/jquery-file-upload/SECURITY.md index db58f7dd7..86ffc163b 100644 --- a/vendor/blueimp/jquery-file-upload/SECURITY.md +++ b/vendor/blueimp/jquery-file-upload/SECURITY.md @@ -113,7 +113,7 @@ location ^~ /path/to/project/server/php/files { ``` ## Secure image processing configurations -The following configuration mitigates [potential image processing vulnerabilities with ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php+imagemagick) by limiting the attack vectors to a small subset of image types (`GIF/JPEG/PNG`). +The following configuration mitigates [potential image processing vulnerabilities with ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php-imagemagick) by limiting the attack vectors to a small subset of image types (`GIF/JPEG/PNG`). Please also consider using alternative, safer image processing libraries like [libvips](https://github.com/libvips/libvips) or [imageflow](https://github.com/imazen/imageflow). diff --git a/vendor/blueimp/jquery-file-upload/angularjs.html b/vendor/blueimp/jquery-file-upload/angularjs.html index 2051bbf79..e8b05e77f 100644 --- a/vendor/blueimp/jquery-file-upload/angularjs.html +++ b/vendor/blueimp/jquery-file-upload/angularjs.html @@ -22,7 +22,7 @@ - + @@ -177,8 +177,8 @@
      - - + + @@ -186,7 +186,7 @@ - + diff --git a/vendor/blueimp/jquery-file-upload/basic-plus.html b/vendor/blueimp/jquery-file-upload/basic-plus.html index acee24843..6d53acdc1 100644 --- a/vendor/blueimp/jquery-file-upload/basic-plus.html +++ b/vendor/blueimp/jquery-file-upload/basic-plus.html @@ -20,7 +20,7 @@ - + @@ -96,15 +96,15 @@ - + - + - + diff --git a/vendor/blueimp/jquery-file-upload/basic.html b/vendor/blueimp/jquery-file-upload/basic.html index 232a24624..a9ef6273e 100644 --- a/vendor/blueimp/jquery-file-upload/basic.html +++ b/vendor/blueimp/jquery-file-upload/basic.html @@ -20,7 +20,7 @@ - + @@ -96,7 +96,7 @@ - + @@ -104,7 +104,7 @@ - + + - + @@ -226,7 +226,7 @@ - + diff --git a/vendor/blueimp/jquery-file-upload/jquery-ui.html b/vendor/blueimp/jquery-file-upload/jquery-ui.html index 842dd4ca7..e44d41e89 100644 --- a/vendor/blueimp/jquery-file-upload/jquery-ui.html +++ b/vendor/blueimp/jquery-file-upload/jquery-ui.html @@ -22,7 +22,7 @@ - + @@ -201,8 +201,8 @@ {% } %} - - + + diff --git a/vendor/blueimp/jquery-file-upload/package.json b/vendor/blueimp/jquery-file-upload/package.json index 4b33a0362..0a635397c 100644 --- a/vendor/blueimp/jquery-file-upload/package.json +++ b/vendor/blueimp/jquery-file-upload/package.json @@ -1,6 +1,6 @@ { "name": "blueimp-file-upload", - "version": "9.25.1", + "version": "9.28.0", "title": "jQuery File Upload", "description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.", "keywords": [ diff --git a/vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php b/vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php old mode 100755 new mode 100644 index e44004395..5215e4c0f --- a/vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php +++ b/vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php @@ -38,9 +38,9 @@ class UploadHandler 'image_resize' => 'Failed to resize image' ); - protected const IMAGETYPE_GIF = 1; - protected const IMAGETYPE_JPEG = 2; - protected const IMAGETYPE_PNG = 3; + const IMAGETYPE_GIF = 1; + const IMAGETYPE_JPEG = 2; + const IMAGETYPE_PNG = 3; protected $image_objects = array(); @@ -1047,13 +1047,18 @@ class UploadHandler } protected function create_scaled_image($file_name, $version, $options) { - if ($this->options['image_library'] === 2) { - return $this->imagemagick_create_scaled_image($file_name, $version, $options); + try { + if ($this->options['image_library'] === 2) { + return $this->imagemagick_create_scaled_image($file_name, $version, $options); + } + if ($this->options['image_library'] && extension_loaded('imagick')) { + return $this->imagick_create_scaled_image($file_name, $version, $options); + } + return $this->gd_create_scaled_image($file_name, $version, $options); + } catch (\Exception $e) { + error_log($e->getMessage()); + return false; } - if ($this->options['image_library'] && extension_loaded('imagick')) { - return $this->imagick_create_scaled_image($file_name, $version, $options); - } - return $this->gd_create_scaled_image($file_name, $version, $options); } protected function destroy_image_object($file_path) { @@ -1066,12 +1071,12 @@ class UploadHandler $fp = fopen($file_path, 'r'); $data = fread($fp, 4); fclose($fp); - // GIF: 47 49 46 - if (substr($data, 0, 3) === 'GIF') { + // GIF: 47 49 46 38 + if ($data === 'GIF8') { return self::IMAGETYPE_GIF; } - // JPG: FF D8 - if (bin2hex(substr($data, 0, 2)) === 'ffd8') { + // JPG: FF D8 FF + if (bin2hex(substr($data, 0, 3)) === 'ffd8ff') { return self::IMAGETYPE_JPEG; } // PNG: 89 50 4E 47 @@ -1082,6 +1087,9 @@ class UploadHandler } protected function is_valid_image_file($file_path) { + if (!preg_match('/\.(gif|jpe?g|png)$/i', $file_path)) { + return false; + } return !!$this->imagetype($file_path); } diff --git a/vendor/blueimp/jquery-file-upload/server/php/index.php b/vendor/blueimp/jquery-file-upload/server/php/index.php index 9c2cfb8eb..6caabb710 100644 --- a/vendor/blueimp/jquery-file-upload/server/php/index.php +++ b/vendor/blueimp/jquery-file-upload/server/php/index.php @@ -9,7 +9,7 @@ * Licensed under the MIT license: * https://opensource.org/licenses/MIT */ -exit; + error_reporting(E_ALL | E_STRICT); require('UploadHandler.php'); $upload_handler = new UploadHandler(); diff --git a/vendor/blueimp/jquery-file-upload/test/index.html b/vendor/blueimp/jquery-file-upload/test/index.html index 0b5cf57b7..b8c585df5 100644 --- a/vendor/blueimp/jquery-file-upload/test/index.html +++ b/vendor/blueimp/jquery-file-upload/test/index.html @@ -20,7 +20,7 @@ jQuery File Upload Plugin Test - +

      jQuery File Upload Plugin Test

      @@ -145,7 +145,7 @@ {% } %} - + @@ -166,7 +166,7 @@ window.testBasicWidget = $.blueimp.fileupload; /* global window, $ */ window.testUIWidget = $.blueimp.fileupload; - + diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index b7cffc67c..86acbb152 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -380,6 +380,9 @@ return array( 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php', 'Ramsey\\Uuid\\BinaryUtils' => $vendorDir . '/ramsey/uuid/src/BinaryUtils.php', 'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', 'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => $vendorDir . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index a02571a95..ea23de753 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -548,6 +548,9 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php', 'Ramsey\\Uuid\\BinaryUtils' => __DIR__ . '/..' . '/ramsey/uuid/src/BinaryUtils.php', 'Ramsey\\Uuid\\Builder\\DefaultUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', 'Ramsey\\Uuid\\Builder\\DegradedUuidBuilder' => __DIR__ . '/..' . '/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index b9c998f12..d2f86ea99 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,20 +1,20 @@ [ { "name": "blueimp/jquery-file-upload", - "version": "v9.25.1", - "version_normalized": "9.25.1.0", + "version": "v9.28.0", + "version_normalized": "9.28.0.0", "source": { "type": "git", "url": "https://github.com/vkhramtsov/jQuery-File-Upload.git", - "reference": "28891f9b2bc339bcc1ca8d548e5401e8563bf04b" + "reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/28891f9b2bc339bcc1ca8d548e5401e8563bf04b", - "reference": "28891f9b2bc339bcc1ca8d548e5401e8563bf04b", + "url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/ff5accfe2e5c4a522777faa980a90cf86a636d1d", + "reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d", "shasum": "" }, - "time": "2018-10-26T07:21:48+00:00", + "time": "2018-11-13T05:41:39+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -498,23 +498,23 @@ }, { "name": "psr/log", - "version": "1.0.2", - "version_normalized": "1.0.2.0", + "version": "1.1.0", + "version_normalized": "1.1.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", "shasum": "" }, "require": { "php": ">=5.3.0" }, - "time": "2016-10-10T12:19:37+00:00", + "time": "2018-11-20T15:27:04+00:00", "type": "library", "extra": { "branch-alias": { @@ -1182,8 +1182,8 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.9.0", - "version_normalized": "1.9.0.0", + "version": "v1.10.0", + "version_normalized": "1.10.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", diff --git a/vendor/psr/log/README.md b/vendor/psr/log/README.md index 574bc1cb2..5571a25e8 100644 --- a/vendor/psr/log/README.md +++ b/vendor/psr/log/README.md @@ -7,6 +7,13 @@ This repository holds all interfaces/classes/traits related to Note that this is not a logger of its own. It is merely an interface that describes a logger. See the specification for more details. +Installation +------------ + +```bash +composer require psr/log +``` + Usage ----- From 3b42bd43abcf70c97c070328e07aad45f85a8945 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Sun, 25 Nov 2018 09:22:09 +0000 Subject: [PATCH 07/24] Do not store serialized pconfig value received via to Module/Pconfig.php (cherry picked from commit 6b02c664fb9444d66322605c408bb791457ee0b5) --- Zotlabs/Module/Pconfig.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Zotlabs/Module/Pconfig.php b/Zotlabs/Module/Pconfig.php index 7c82bac7d..bf8e32dff 100644 --- a/Zotlabs/Module/Pconfig.php +++ b/Zotlabs/Module/Pconfig.php @@ -22,6 +22,11 @@ class Pconfig extends \Zotlabs\Web\Controller { $k = trim(escape_tags($_POST['k'])); $v = trim($_POST['v']); $aj = intval($_POST['aj']); + + // Do not store "serialized" data received in the $_POST + if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('O:8:"stdClass":[0-9]+:{.*}$|s',$v)) { + return; + } if(in_array(argv(2),$this->disallowed_pconfig())) { notice( t('This setting requires special processing and editing has been blocked.') . EOL); From 58c0b81908a2d6ec1b60cf3762a920b652649cf9 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 26 Nov 2018 11:44:10 +0000 Subject: [PATCH 08/24] use flex for the default template (cherry picked from commit 3775be4ce9c56639146efa877eefabb9e9f23b3c) --- view/css/default.css | 37 ++++++++++++++++++++++++++----------- view/css/mod_connedit.css | 1 - view/php/default.php | 14 +++++++++----- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/view/css/default.css b/view/css/default.css index 765a197d9..bd0f14ba2 100644 --- a/view/css/default.css +++ b/view/css/default.css @@ -1,22 +1,37 @@ main { - display: table; - table-layout: fixed; position: relative; - width: 100%; - height: 100vh; + min-height: 100vh; + display: flex; + flex-direction: column; } -aside { +.content { + display: flex; + flex: 1; +} + +.columns { + display: flex; + flex:1; + min-width: 0; +} + +#region_1 { position: relative; - display: table-cell; - vertical-align: top; + order: 1; padding: 4.5rem 7px 0px 7px; } -section { +#region_2 { position: relative; - width: 100%; - display: table-cell; - vertical-align: top; + flex: 1; + order: 2; padding: 4.5rem 7px 200px 7px; + min-width: 0; +} + +#region_3 { + position: relative; + order: 3; + padding: 4.5rem 7px 0px 7px; } diff --git a/view/css/mod_connedit.css b/view/css/mod_connedit.css index 67a182c5c..b02f928f0 100644 --- a/view/css/mod_connedit.css +++ b/view/css/mod_connedit.css @@ -71,7 +71,6 @@ width: 32px; height: 32px; border-radius: 4px; - border: 1px solid #ccc; text-align: center; } diff --git a/view/php/default.php b/view/php/default.php index 60f3f6a6f..388c94382 100644 --- a/view/php/default.php +++ b/view/php/default.php @@ -10,12 +10,16 @@
      - -
      +
      +
      + +
      -
      -
      - +
      +
      + + +
      From 71cc980e96e7408c8f415d5c752f9f93c5c1ed45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Jim=C3=A9nez=20Friaza?= Date: Mon, 26 Nov 2018 11:43:24 +0000 Subject: [PATCH 09/24] Revision 1 doc/es-es/about/about.bb (cherry picked from commit 5ac08ec3aa8ede14141390670a8097a60769e11e) (cherry picked from commit 37d563c30ed2db7aba04537af8e90324d55c71f0) --- doc/es-es/about/about.bb | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/doc/es-es/about/about.bb b/doc/es-es/about/about.bb index 1d5f3a4a2..50d23c778 100644 --- a/doc/es-es/about/about.bb +++ b/doc/es-es/about/about.bb @@ -29,7 +29,7 @@ $Projectname es, básicamente, una aplicación de servidor web relativamente est [*= Identidad nómada] La capacidad de autenticar y migrar fácilmente una identidad a través de hubs y dominios web independientes. La identidad nómada proporciona una verdadera propiedad de una identidad en línea, porque las identidades de los canales controlados por una cuenta en un hub no están vinculadas al propio hub. Un hub es más como un "host" para canales. Con Hubzilla, no tienes una "cuenta" en un servidor como lo haces en sitios web típicos; tienes una identidad que puedes llevarte a través de la rejilla usando clones. -[*= Zot] El novedoso protocolo basado en JSON para la implementación de comunicaciones y servicios descentralizados seguros. Se diferencia de muchos otros protocolos de comunicación en que construye las comunicaciones sobre un marco de identidad y autenticación descentralizado. El componente de autenticación es similar a OpenID conceptualmente pero está aislado de las identidades basadas en DNS. Cuando es posible, la autenticación remota es silenciosa e invisible. Esto proporciona un mecanismo para el control de acceso distribuido a escala de Internet que es discreto. +[*= Zot] El novedoso protocolo basado en JSON para la implementación de comunicaciones y servicios descentralizados seguros. Se diferencia de muchos otros protocolos de comunicación en que construye las comunicaciones sobre un marco de identidad y autenticación descentralizado. El componente de autenticación es similar a OpenID conceptualmente pero está aislado de las identidades basadas en DNS. Cuando es posible, la autenticación remota es silenciosa e invisible. Esto proporciona un mecanismo discreto para el control de acceso distribuido a escala de Internet. [/dl] @@ -41,7 +41,7 @@ Esta página enumera algunas de las características principales de $Projectname [h4]Control deslizante de afinidad[/h4] Cuando se añaden conexiones en $Projectname, los miembros tienen la opción de asignar niveles de "afinidad" (cuán cerca está su amigo). -Por otro lado, al añadir el canal de un amigo, se puede situar bajo el nivel de afinidad de "Amigos". +Por otro lado, al añadir el canal de un amigo, se puede situar bajo el nivel de afinidad, justamente, de "Amigos". En este punto, la herramienta $Projectname [i]Control deslizante de afinidad[/i], que normalmente aparece en la parte superior de la página, ajusta su contenido para incluir aquellos contactos que están dentro del rango de afinidad deseado. Los canales fuera de ese rango no se mostrarán, a menos que ajuste el control deslizante para incluirlos. @@ -62,7 +62,7 @@ Las listas de control de acceso se pueden aplicar a contenido y mensajes, fotos, [h4]Inicio de sesión único[/h4] -Las listas de control de acceso funcionan para todos los canales de la red gracias a nuestra exclusiva tecnología de inicio de sesión único. La mayoría de los enlaces internos proporcionan un token de identidad que puede ser verificado en otros sitios de $Projectname y utilizado para controlar el acceso a recursos privados. Inicie sesión una vez en el hub de su casa. Después de eso, la autenticación de todos los recursos de $Projectname es "mágica". +Las listas de control de acceso funcionan para todos los canales de la red gracias a nuestra exclusiva tecnología de inicio de sesión único. La mayoría de los enlaces internos proporcionan un token de identidad que puede ser verificado en otros sitios de $Projectname y utilizado para controlar el acceso a recursos privados. Inicie sesión una vez en la página principal del hub. Después de eso, la autenticación de todos los recursos de $Projectname es "mágica". [h4]Almacenamiento de Archivos habilitado para WebDAV[/h4] @@ -93,7 +93,7 @@ Las aplicaciones pueden ser construidas y distribuidas por los miembros. Éstas [h4]Diseño[/h4] -El diseño de la página se basa en un lenguaje de descripción llamado comanche. La propia $Projectname está escrito en diseños comanches que se pueden cambiar. Esto permite un nivel de personalización que no se encuentra normalmente en los llamados "entornos multiusuario". +El diseño de la página se basa en un lenguaje de descripción llamado comanche. La propia $Projectname está escrito en plantillas en comanche que se pueden cambiar. Esto permite un nivel de personalización que no se encuentra normalmente en los llamados "entornos multiusuario". [h4]Marcadores[/h4] @@ -111,14 +111,14 @@ Además, los mensajes pueden crearse utilizando "encriptación de extremo a extr Por lo general, los mensajes públicos no se cifran durante el transporte ni durante el almacenamiento. -Los mensajes privados pueden ser revocados (no enviados) aunque no hay garantía de que el destinatario no lo haya leído todavía. +Los mensajes privados pueden ser revocados (no enviados) aunque no hay garantía de que el destinatario no lo haya leído antes. Los mensajes se pueden crear con una fecha de caducidad, en la que se borrarán/quitarán en el sitio del destinatario. [h4]Federación de Servicios[/h4] -Además de añadir "conectores de publicación cruzada" a una variedad de redes alternativas, hay soporte nativo para la importación de contenido desde RSS/Atom feeds y puede utilizarlo para crear canales especiales. Los plugins también están disponibles para comunicarse con otros usando los protocolos Diáspora, GNU-Social (OStatus) o Mastodon (ActivityPub). Estas redes no soportan la identidad nómada ni el control de acceso entre dominios; sin embargo, las comunicaciones básicas son soportadas desde/hacia la diáspora, Friendica, GNU-Social, Mastodon y otros proveedores que utilizan estos protocolos. +Además de añadir "conectores de publicación cruzada" a una variedad de redes alternativas, hay soporte nativo para la importación de contenido desde RSS/Atom feeds y puede utilizarlo para crear canales especiales. Los plugins también están disponibles para comunicarse con otros usando los protocolos Diáspora, GNU-Social (OStatus) o Mastodon (ActivityPub). Estas redes no soportan la identidad nómada ni el control de acceso entre dominios; sin embargo, las comunicaciones básicas son soportadas desde o hacia Diaspora, Friendica, GNU-Social, Mastodon, Pleroma y otros proveedores que utilizan estos protocolos. También existe soporte experimental para la autenticación OpenID que puede utilizarse en las listas de control de acceso. Este es un trabajo en progreso. Su hub $Projectname puede ser utilizado como un proveedor de OpenID para autenticarle en servicios externos que utilizan esta tecnología. @@ -126,7 +126,7 @@ Los canales pueden tener permisos para convertirse en "canales derivados" cuando [h4]Grupos de Privacidad[/h4] -Nuestra implementación de grupos de privacidad es similar a la de Google "Círculos" y "Aspectos" de la Diáspora. Esto le permite filtrar su flujo entrante por grupos seleccionados y establecer automáticamente la Lista de control de acceso saliente sólo para aquellos que se encuentren en ese grupo de privacidad cuando publique. Usted puede anular esto en cualquier momento (antes de enviar el correo). +Nuestra implementación de grupos de privacidad es similar a la de Google "Círculos" y "Aspectos" de Diaspora. Esto le permite filtrar su flujo entrante por grupos seleccionados y establecer automáticamente la Lista de control de acceso saliente sólo para aquellos que se encuentren en ese grupo de privacidad cuando publique. Usted puede anular esto en cualquier momento (antes de enviar el correo). [h4]Servicios de directorio[/h4] @@ -158,19 +158,25 @@ Las opciones son: [h4]Foros Públicos y Privados[/h4] -Los foros son típicamente canales que pueden estar abiertos a la participación de múltiples autores. Actualmente existen dos mecanismos para enviar mensajes a los foros: 1) mensajes de "muro a muro" y 2) a través de las etiquetas @mención del foro. Los foros pueden ser creados por cualquier persona y utilizados para cualquier propósito. El directorio contiene una opción para buscar foros públicos. Los foros privados sólo pueden ser publicados y, a menudo, sólo pueden ser vistos por los miembros. +Los foros son típicamente canales que pueden estar abiertos a la participación de múltiples autores. Actualmente existen dos mecanismos para enviar mensajes a los foros: + +1) mensajes de "muro a muro" y + +2) a través de las etiquetas @mención del foro. + +Los foros pueden ser creados por cualquier persona y utilizados para cualquier propósito. El directorio contiene una opción para buscar foros públicos. Los foros privados sólo pueden ser publicados y, a menudo, sólo pueden ser vistos por los miembros. [h4]Clonación de cuentas[/h4] -Las cuentas en $Projectname se denominan [i]identidades nómadas[/i], porque la identidad de un miembro no está vinculada al hub donde se creó la identidad originalmente. Por ejemplo, cuando creas una cuenta de Facebook o Gmail, está vinculada a esos servicios. No pueden funcionar sin Facebook.com o Gmail.com. +Las cuentas en $Projectname se denominan [i]identidades nómadas[/i], porque la identidad de un miembro no está vinculada al hub donde se creó la identidad originalmente. Por ejemplo, cuando cree una cuenta de Facebook o Gmail, está vinculada a esos servicios. No pueden funcionar sin Facebook.com o Gmail.com. -Por el contrario, digamos que ha creado una identidad $Projectname llamada[b]tina@$Projectnamehub.com[/b]. Puede clonarlo a otro hub $Projectname eligiendo el mismo o un nombre diferente:[b]vivoParasiempre@algún$ProjectnameHub.info[/b] +Por el contrario, digamos que ha creado una identidad $Projectname llamada [b]tina@$Projectnamehub.com[/b]. Puede clonarlo a otro hub $Projectname eligiendo el mismo o un nombre diferente:[b]vivoParasiempre@algún$ProjectnameHub.info[/b] -Ahora ambos canales están sincronizados, lo que significa que todos sus contactos y preferencias se duplicarán en su clon. No importa si envías un mensaje desde su hub original o desde el nuevo hub. Los mensajes se reflejarán en ambas cuentas. +Ahora ambos canales están sincronizados, lo que significa que todos sus contactos y preferencias se duplicarán en su clon. No importa si envía un mensaje desde su hub original o desde el nuevo hub. Los mensajes se reflejarán en ambas cuentas. Esta es una característica bastante revolucionaria, si consideramos algunos escenarios: - ¿Qué ocurre si el hub en el que se basa una identidad se desconecta de repente? Sin clonación, un miembro no podrá comunicarse hasta que el hub vuelva a estar en línea (sin duda muchos de ustedes han visto y maldecido el Twitter "Fail Whale"). Con la clonación, sólo tienesque iniciar sesión en su cuenta clonada y la vida continúa feliz para siempre. + ¿Qué ocurre si el hub en el que se basa una identidad se desconecta de repente? Sin clonación, un miembro no podrá comunicarse hasta que el hub vuelva a estar en línea (sin duda muchos de ustedes han visto y maldecido el Twitter "Fail Whale"). Con la clonación, sólo tiene que iniciar sesión en su cuenta clonada y la vida continúa feliz para siempre. El administrador de su hub ya no puede permitirse el lujo de pagar por su hub gratuito y público $Projectname. Anuncia que el centro cerrará en dos semanas. Esto le da tiempo suficiente para clonar su(s) identidad(es) y preservar las relaciones, amigos y contenido de su $Projectname. @@ -193,9 +199,10 @@ $Projectname ofrece una sencilla copia de seguridad de la cuenta con un solo cli [h4]Borrado de cuenta[/h4] -Las cuentas se pueden eliminar inmediatamente haciendo clic en un enlace. Eso es todo. Todo el contenido asociado se elimina de la rejilla (esto incluye los mensajes y cualquier otro contenido producido por el perfil eliminado). Dependiendo del número de conexiones que tenga, el proceso de eliminación de contenido remoto podría llevar algún tiempo, pero está previsto que ocurra tan rápido como sea posible. +Las cuentas se pueden eliminar inmediatamente haciendo clic en un enlace. Eso es todo. Todo el contenido asociado se elimina de la red (esto incluye los mensajes y cualquier otro contenido producido por el perfil eliminado). Dependiendo del número de conexiones que tenga, el proceso de eliminación de contenido remoto podría llevar algún tiempo, pero está previsto que ocurra tan rápido como sea posible. [h4]Supresión de contenido[/h4] + Cualquier contenido creado en $Projectname permanece bajo el control del miembro (o canal) que lo creó originalmente. En cualquier momento, un miembro puede borrar un mensaje o un rango de mensajes. El proceso de eliminación garantiza que el contenido se elimine, independientemente de si se publicó en el hub principal de un canal o en otro hub, donde el canal se autenticó de forma remota a través de Zot (protocolo de autenticación y comunicación de $Projectname). @@ -221,4 +228,4 @@ $Projectname se puede ampliar de varias maneras, a través de la personalizació [h4]API[/h4] -Una API está disponible para su uso por parte de servicios de terceros. Un plugin también proporciona una implementación básica de Twitter (para los que existen cientos de herramientas de terceros). El acceso puede ser proporcionado por login/contraseña o OAuth, y el registro del cliente de las aplicaciones de OAuth es proporcionado. \ No newline at end of file +Una API está disponible para su uso por parte de servicios de terceros. Un plugin también proporciona una implementación básica de Twitter (para los que existen cientos de herramientas de terceros). El acceso puede ser proporcionado por login/contraseña o OAuth, y el registro del cliente de las aplicaciones de OAuth está disponible. \ No newline at end of file From 4bf3d4d87ac23af339f6418055211037b020cf1d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 30 Nov 2018 21:54:17 +0000 Subject: [PATCH 10/24] attached photo permissions regression (cherry picked from commit 6cade7d935a489349c56165139796bd2f9cf9be6) --- include/items.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/items.php b/include/items.php index c1613ea8c..72bb1dca4 100755 --- a/include/items.php +++ b/include/items.php @@ -4610,10 +4610,10 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body, if(! stristr($image,z_root() . '/photo/')) continue; $image_uri = substr($image,strrpos($image,'/') + 1); - if(strpos($image_uri,'-') !== false) - $image_uri = substr($image_uri,0, strpos($image_uri,'-')); - if(strpos($image_uri,'.') !== false) - $image_uri = substr($image_uri,0, strpos($image_uri,'.')); + if(strrpos($image_uri,'-') !== false) + $image_uri = substr($image_uri,0, strrpos($image_uri,'-')); + if(strrpos($image_uri,'.') !== false) + $image_uri = substr($image_uri,0, strrpos($image_uri,'.')); if(! strlen($image_uri)) continue; $srch = '<' . $xchan_hash . '>'; From 4b4cc0489729e061f18a825e0e0be3fa0a9d8353 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 1 Dec 2018 03:03:14 +0000 Subject: [PATCH 11/24] allow notification filtering by name or addr (cherry picked from commit c6acb6191ca558fce121e7df26a8aba88beac2d9) --- Zotlabs/Lib/Enotify.php | 1 + Zotlabs/Module/Ping.php | 8 +++++++- view/js/main.js | 2 +- view/tpl/notifications_widget.tpl | 13 +++++++------ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php index 25c96d9cc..523ccf93a 100644 --- a/Zotlabs/Lib/Enotify.php +++ b/Zotlabs/Lib/Enotify.php @@ -828,6 +828,7 @@ class Enotify { $x = array( 'notify_link' => $item['llink'], 'name' => $item['author']['xchan_name'], + 'addr' => $item['author']['xchan_addr'], 'url' => $item['author']['xchan_url'], 'photo' => $item['author']['xchan_photo_s'], 'when' => relative_date(($edit)? $item['edited'] : $item['created']), diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php index f660c3b55..12244d88c 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -330,6 +330,7 @@ class Ping extends \Zotlabs\Web\Controller { $notifs[] = array( 'notify_link' => z_root() . '/mail/' . $zz['id'], 'name' => $zz['xchan_name'], + 'addr' => $zz['xchan_addr'], 'url' => $zz['xchan_url'], 'photo' => $zz['xchan_photo_s'], 'when' => relative_date($zz['created']), @@ -383,6 +384,7 @@ class Ping extends \Zotlabs\Web\Controller { $result[] = array( 'notify_link' => z_root() . '/connections/ifpending', 'name' => $rr['xchan_name'], + 'addr' => $rr['xchan_addr'], 'url' => $rr['xchan_url'], 'photo' => $rr['xchan_photo_s'], 'when' => relative_date($rr['abook_created']), @@ -407,6 +409,7 @@ class Ping extends \Zotlabs\Web\Controller { $result[] = array( 'notify_link' => z_root() . '/admin/accounts', 'name' => $rr['account_email'], + 'addr' => $rr['account_email'], 'url' => '', 'photo' => z_root() . '/' . get_default_profile_photo(48), 'when' => relative_date($rr['account_created']), @@ -444,6 +447,7 @@ class Ping extends \Zotlabs\Web\Controller { $result[] = array( 'notify_link' => z_root() . '/events', /// @FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'], 'name' => $rr['xchan_name'], + 'addr' => $rr['xchan_addr'], 'url' => $rr['xchan_url'], 'photo' => $rr['xchan_photo_s'], 'when' => $when, @@ -460,7 +464,7 @@ class Ping extends \Zotlabs\Web\Controller { if(argc() > 1 && (argv(1) === 'files')) { $result = array(); - $r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_url, xchan.xchan_photo_s FROM item + $r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM item LEFT JOIN xchan on author_xchan = xchan_hash WHERE item.verb = '%s' AND item.obj_type = '%s' @@ -477,6 +481,7 @@ class Ping extends \Zotlabs\Web\Controller { $result[] = array( 'notify_link' => z_root() . '/sharedwithme', 'name' => $rr['xchan_name'], + 'addr' => $rr['xchan_addr'], 'url' => $rr['xchan_url'], 'photo' => $rr['xchan_photo_s'], 'when' => relative_date($rr['created']), @@ -658,6 +663,7 @@ class Ping extends \Zotlabs\Web\Controller { if($r[0]['unseen']) { $forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id']); $forums[$x]['name'] = $forums[$x]['xchan_name']; + $forums[$x]['addr'] = $forums[$x]['xchan_addr']; $forums[$x]['url'] = $forums[$x]['xchan_url']; $forums[$x]['photo'] = $forums[$x]['xchan_photo_s']; $forums[$x]['unseen'] = $r[0]['unseen']; diff --git a/view/js/main.js b/view/js/main.js index 085bc8d0d..f4bfd413b 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -544,7 +544,7 @@ function handleNotificationsItems(notifyType, data) { notify_menu.html(''); $(data).each(function() { - html = notifications_tpl.format(this.notify_link,this.photo,this.name,this.message,this.when,this.hclass,this.b64mid,this.notify_id,this.thread_top,this.unseen,this.private_forum); + html = notifications_tpl.format(this.notify_link,this.photo,this.name,this.addr,this.message,this.when,this.hclass,this.b64mid,this.notify_id,this.thread_top,this.unseen,this.private_forum); notify_menu.append(html); }); diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl index f43d82301..48521c81c 100644 --- a/view/tpl/notifications_widget.tpl +++ b/view/tpl/notifications_widget.tpl @@ -105,8 +105,9 @@ $("#nav-{{$notification.type}}-menu .notification").each(function(i, el){ var cn = $(el).data('contact_name').toString().toLowerCase(); + var ca = $(el).data('contact_addr').toString().toLowerCase(); - if(cn.indexOf(val) === -1) + if(cn.indexOf(val) === -1 && ca.indexOf(val) === -1) $(this).addClass('d-none'); else $(this).removeClass('d-none'); @@ -134,18 +135,18 @@ {{$no_notifications}}...