问:
How to apply separate CSS styles to divs in a loop with JS?
I have two divs and each div contains two nested divs. If one of the nested divs is taller in height than the other I want certain CSS styles to be applied.

I've managed to get the alerts to work correctly, however I'm a getting a little confused as the CSS styles seem to be applying to both divs.

Any help with finishing this off would be greatly appreciated.

Heres the demo https://jsfiddle.net/Lhn5uxeq/3/

HTML

```<code><div class="slideshow" data-id="1">
  <div class="slideshow-info">
    <h1>
     Header
    </h1>
    <p>
     Text
    </p>
  </div>
  <div class="slideshow-image">
    <img src="https://www.w3schools.com/css/img_fjords.jpg"/>
  </div>
</div>
<div class="slideshow" data-id="2">
  <div class="slideshow-info">
    <h1>
     Header
    </h1>
    <p>
     Text Text Text Text Text Text Text Text Text Text Text Text Text  Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.
    </p>
  </div>
  <div class="slideshow-image">
    <img src="https://www.w3schools.com/css/img_fjords.jpg"/>
  </div>
</div>
</code>```

JS

```<code>$(document).ready(function(){
  calculateHeight();

  $(window).resize(function() {
    calculateHeight();
  });
});

function calculateHeight() {
  $('.slideshow').each(function() {
    $('.slideshow-info', this).each(function() {
      slideInfoHeight = $(this).height();
    });
    $('.slideshow-image', this).each(function() {
      slideImageHeight = $(this).height();
    });

    if(slideInfoHeight > slideImageHeight) {
      alert('info is taller than image');
      $('.slideshow-info').css('background-color', 'red');
    } else {
      alert ('info is shorter than image');
      $('.slideshow-info').css('background-color', 'blue');
    }
  });
}
</code>```

答:
You have to apply the css for the div in that specific slideshow only. below code will work.
https://jsfiddle.net/Lhn5uxeq/5/</p>

```<code>function calculateHeight() {
  $('.slideshow').each(function() {
    $('.slideshow-info', this).each(function() {
      slideInfoHeight = $(this).height();
    });
    $('.slideshow-image', this).each(function() {
      slideImageHeight = $(this).height();
    });

    if(slideInfoHeight > slideImageHeight) {
      alert('info is taller than image');
       $( this ).find( '.slideshow-info' ).css('background-color', 'red');
    } else {
      alert ('info is shorter than image');
      $( this ).find( '.slideshow-info' ).css('background-color', 'blue');
    }
  });
</code>```

Body:
I have two divs and each div contains two nested divs. If one of the nested divs is taller in height than the other I want certain CSS styles to be applied.

I've managed to get the alerts to work correctly, however I'm a getting a little confused as the CSS styles seem to be applying to both divs.

Any help with finishing this off would be greatly appreciated.

Heres the demo https://jsfiddle.net/Lhn5uxeq/3/

HTML

     Header

     Text

     Header

     Text Text Text Text Text Text Text Text Text Text Text Text Text  Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.

JS

$(document).ready(function(){
  calculateHeight();

  $(window).resize(function() {
    calculateHeight();
  });
});

function calculateHeight() {
  $('.slideshow').each(function() {
    $('.slideshow-info', this).each(function() {
      slideInfoHeight = $(this).height();
    });
    $('.slideshow-image', this).each(function() {
      slideImageHeight = $(this).height();
    });

    if(slideInfoHeight > slideImageHeight) {
      alert('info is taller than image');
      $('.slideshow-info').css('background-color', 'red');
    } else {
      alert ('info is shorter than image');
      $('.slideshow-info').css('background-color', 'blue');
    }
  });
}

Body:
You have to apply the css for the div in that specific slideshow only. below code will work.
https://jsfiddle.net/Lhn5uxeq/5/

function calculateHeight() {
  $('.slideshow').each(function() {
    $('.slideshow-info', this).each(function() {
      slideInfoHeight = $(this).height();
    });
    $('.slideshow-image', this).each(function() {
      slideImageHeight = $(this).height();
    });

    if(slideInfoHeight > slideImageHeight) {
      alert('info is taller than image');
       $( this ).find( '.slideshow-info' ).css('background-color', 'red');
    } else {
      alert ('info is shorter than image');
      $( this ).find( '.slideshow-info' ).css('background-color', 'blue');
    }
  });


来源: stackexchange

问:
How to speedup generating urls?
I have the following method that generates URLs for me:

```<code>async def get_url_for_ids(self, ids: List[int]) -> List[str]:
    urls = []
    async with self.session.create_client('s3', region_name=self.region_name) as s3:
        for id in ids:
            url = s3.generate_presigned_url(ClientMethod='get_object',
                  Params={'Bucket': self.bucket_with_videos,  'Key': '{}.mp4'.format(id)})
            urls.append(url)
    return urls
</code>```

This method is the slowest part in my app. Even query to the DB works much faster. get_url_for_ids works around 15 sec if ids contains for example 30,000 elements.

How to speed up it?

答: You don't say what size self.bucket_with_videos is but I suspect it is large and the API is doing a linear, or possibly accidentally quadratic1, search over it.</p>

ContentLicense: CC BY-SA 3.0

Title: How to speedup generating urls?

Body:
I have the following method that generates URLs for me:

async def get_url_for_ids(self, ids: List[int]) -> List[str]:
    urls = []
    async with self.session.create_client('s3', region_name=self.region_name) as s3:
        for id in ids:
            url = s3.generate_presigned_url(ClientMethod='get_object',
                  Params={'Bucket': self.bucket_with_videos,  'Key': '{}.mp4'.format(id)})
            urls.append(url)
    return urls

This method is the slowest part in my app. Even query to the DB works much faster. get_url_for_ids works around 15 sec if ids contains for example 30,000 elements.

How to speed up it?


问:
Task progress from a ZeroMQ worker
Fairly new to ZeroMQ. I have a simple REQ/REP queue like below. I am using PHP but that doesn't matter as any language binding would be fine for me.
This is client to request a task

```<code>$ctx = new ZMQContext();
$req = new ZMQSocket($ctx, ZMQ::SOCKET_REQ);
$req->connect('tcp://localhost:5454');
$req->send("Export Data as Zip");
echo $i . ":" . $req->recv().PHP_EOL;
</code>```

And this is a worker to actually perform the task.

```<code>$ctx = new ZMQContext();
$srvr = new ZMQSocket($ctx, ZMQ::SOCKET_REP);
$srvr->bind("tcp://*:5454");
echo "Server is started at port $port" . PHP_EOL;
while(true)
{
    $msg = $srvr->recv();
    echo "Message = " . $msg . PHP_EOL;
    // Do the work here, takes 10 min, knows the count of lines added and remaining
    $srvr->send($msg . " is exported as zip file" . date('H:i:s'));
}
</code>```

As the task of exporting data takes about 10 min, I want to connect to the server from a different client and get the progress/ percentage of the task done.
I am wondering if that's even a valid approach.

I tried this approach where REQ/REP part works but I get nothing in PUB/SUB part

Server part

```<code>$ctx = new ZMQContext();
$srvr = new ZMQSocket($ctx, ZMQ::SOCKET_REP);
$srvr->bind("tcp://*:5454");

// add PUB socket to publish progress
$c = new ZMQContext();
$p = new ZMQSocket($c, ZMQ::SOCKET_PUB);
$p->bind("tcp://*:5460");

echo "Server is started at port 5454" . PHP_EOL;
$prog = 0;
while(true)
{
    $p->send($prog++ . '%'); // this part doesn't get to the progress client
    $msg = $srvr->recv();
    echo "Message = " . $msg . PHP_EOL;
    sleep(2);// some long task
    $srvr->send($msg . " Done zipping " . date('H:i:s'));
}
</code>```

Progress client

```<code>$ctx = new ZMQContext();
$stat = new ZMQSocket($ctx, ZMQ::SOCKET_SUB);
$stat->connect('tcp://localhost:5460');
while (true){
    echo $stat->recv() . PHP_EOL; //nothing shows here
}
</code>```

Request client

```<code>$ctx = new ZMQContext();
$req = new ZMQSocket($ctx, ZMQ::SOCKET_REQ);
$req->connect('tcp://localhost:5454');
for($i=0;$i<100;$i++){
    $req->send("$i : Zip the file please");
    echo $i . ":" . $req->recv().PHP_EOL; //works and get the output
}
</code>```

答:
The concept is feasible, some tuning needed:

All PUB counterparties have to setup any non-default subscription, via, at least an empty subscription .setsockopt( ZMQ_SUBSCRIBE, "" ) meaning receive all TOPICs ( none "filter"-ed out ).

Next, both PUB-side and SUB sides ought get .setsockopt( ZMQ_CONFLATE, 1 ) configured, as there is of no value to populate and feed all intermediate values into the en-queue/de-queue pipeline, once the only value is in the "last", most recent message.

Always, the non-blocking mode of the ZeroMQ calls ought be preferred ( .recv( ..., flags = ZMQ_NOBLOCK ) et al ) or the  Poller.poll() pre-tests ought be used to sniff first for a (non)-presence of a message, before spending more efforts on reading its context "from" ZeroMQ context-manager. Simply put, there are not many cases, where blocking-mode service calls may serve well in a production-grade system.

Also some further tweaking may help the PUB side, in case a more massive "attack" comes from the un-restricted pool of SUB-side entities and PUB has to create / manage / maintain resources for each of these ( unrestricted ) counterparties.

Title: Task progress from a ZeroMQ worker

Body:
Fairly new to ZeroMQ. I have a simple REQ/REP queue like below. I am using PHP but that doesn't matter as any language binding would be fine for me.
This is client to request a task

$ctx = new ZMQContext();
$req = new ZMQSocket($ctx, ZMQ::SOCKET_REQ);
$req->connect('tcp://localhost:5454');
$req->send("Export Data as Zip");
echo $i . ":" . $req->recv().PHP_EOL;

And this is a worker to actually perform the task.

$ctx = new ZMQContext();
$srvr = new ZMQSocket($ctx, ZMQ::SOCKET_REP);
$srvr->bind("tcp://*:5454");
echo "Server is started at port $port" . PHP_EOL;
while(true)
{
    $msg = $srvr->recv();
    echo "Message = " . $msg . PHP_EOL;
    // Do the work here, takes 10 min, knows the count of lines added and remaining
    $srvr->send($msg . " is exported as zip file" . date('H:i:s'));
}

As the task of exporting data takes about 10 min, I want to connect to the server from a different client and get the progress/ percentage of the task done.
I am wondering if that's even a valid approach.

I tried this approach where REQ/REP part works but I get nothing in PUB/SUB part

Server part

$ctx = new ZMQContext();
$srvr = new ZMQSocket($ctx, ZMQ::SOCKET_REP);
$srvr->bind("tcp://*:5454");

// add PUB socket to publish progress
$c = new ZMQContext();
$p = new ZMQSocket($c, ZMQ::SOCKET_PUB);
$p->bind("tcp://*:5460");

echo "Server is started at port 5454" . PHP_EOL;
$prog = 0;
while(true)
{
    $p->send($prog++ . '%'); // this part doesn't get to the progress client
    $msg = $srvr->recv();
    echo "Message = " . $msg . PHP_EOL;
    sleep(2);// some long task
    $srvr->send($msg . " Done zipping " . date('H:i:s'));
}

Progress client

$ctx = new ZMQContext();
$stat = new ZMQSocket($ctx, ZMQ::SOCKET_SUB);
$stat->connect('tcp://localhost:5460');
while (true){
    echo $stat->recv() . PHP_EOL; //nothing shows here
}

Request client

$ctx = new ZMQContext();
$req = new ZMQSocket($ctx, ZMQ::SOCKET_REQ);
$req->connect('tcp://localhost:5454');
for($i=0;$i<100;$i++){
    $req->send("$i : Zip the file please");
    echo $i . ":" . $req->recv().PHP_EOL; //works and get the output
}


问:
html email body sent using javamail api appears garbled in outlook
I am using below code to send mail to multiple users across different domains.

```<code>        String emailBody = "<html>Some html text goes here</html>"
    String from = "from@domain1.com"
    String bcc = "bcc@domain2.com"
    String subject = "Some subject..."
    List attachments = "Some image attachments ..."
    MimeMessage message = new MimeMessage(session);
    message.setHeader("Content-Type", "text/html; charset=UTF-16")
    message.setHeader("Accept-Language", "en-US")
    message.setHeader("Content-Language", "en-US")

    message.setFrom(new InternetAddress(from));
    message.setRecipients(Message.RecipientType.BCC,InternetAddress.parse(bcc));
    message.setSubject(subject);

    // creates message part
    MimeBodyPart messageBodyPart = new MimeBodyPart();
    messageBodyPart.setContent(emailBody, "text/html; charset=UTF-16");

    // creates multi-part
    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);

    addAttachmentsToMultiPart(multipart,attachments)

    message.setContent(multipart);

    Transport.send(message);
</code>```

The email body is entirely is in English. But users of few domains are recieving it in Chinese characters. When I viewed the html source of the body, I found it is partially garbled. Some orginal html text is intact and some junk characters in between text with no particular order. This mail travels this path "Tomcat application -> company mail server -> outlook.office365.com server -> target mail server -> End user outlook client".

After some research, I found this issue could be due to Character encoding. For testing it, I tried sending this mail to gamil.com. The mail body appears correctly in gmail, but I notice following headers are found in headers part and entire body part is base64 encoded.

```<code>Content-Type: text/html; charset="UTF-16"
Content-Transfer-Encoding: base64
</code>```

I am not sure how "Content-Transfer-Encoding" is being set on headers and where is mail body getting encoded. But I don't see similar headers in End User mail properties. I tried explicitly setting "Content-Transfer-Encoding" to "base64", "quoted-printable" ( and other types), but it is always ignored and gmail always recieves it as base64. And this setting has no impact end user mails. They always recieves same garbage.

Can anyone help me understand what could be issue and how to resolve it

答:
I resolved after lot of research and experiment. There were basically two issues

Character-set should not be set at MimeMessage level but at individual MimeBodyPart level.

Changed the UTF-16 to UTF-8. Some email client/server cannot handle UTF-16 properly or they are not configured to handle UTF-16.

Body:
I am using below code to send mail to multiple users across different domains.

        String emailBody = "Some html text goes here"
    String from = "from@domain1.com"
    String bcc = "bcc@domain2.com"
    String subject = "Some subject..."
    List attachments = "Some image attachments ..."
    MimeMessage message = new MimeMessage(session);
    message.setHeader("Content-Type", "text/html; charset=UTF-16")
    message.setHeader("Accept-Language", "en-US")
    message.setHeader("Content-Language", "en-US")

    message.setFrom(new InternetAddress(from));
    message.setRecipients(Message.RecipientType.BCC,InternetAddress.parse(bcc));
    message.setSubject(subject);

    // creates message part
    MimeBodyPart messageBodyPart = new MimeBodyPart();
    messageBodyPart.setContent(emailBody, "text/html; charset=UTF-16");

    // creates multi-part
    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);

    addAttachmentsToMultiPart(multipart,attachments)

    message.setContent(multipart);

    Transport.send(message);

The email body is entirely is in English. But users of few domains are recieving it in Chinese characters. When I viewed the html source of the body, I found it is partially garbled. Some orginal html text is intact and some junk characters in between text with no particular order. This mail travels this path "Tomcat application -> company mail server -> outlook.office365.com server -> target mail server -> End user outlook client".

After some research, I found this issue could be due to Character encoding. For testing it, I tried sending this mail to gamil.com. The mail body appears correctly in gmail, but I notice following headers are found in headers part and entire body part is base64 encoded.

Content-Type: text/html; charset="UTF-16"
Content-Transfer-Encoding: base64

I am not sure how "Content-Transfer-Encoding" is being set on headers and where is mail body getting encoded. But I don't see similar headers in End User mail properties. I tried explicitly setting "Content-Transfer-Encoding" to "base64", "quoted-printable" ( and other types), but it is always ignored and gmail always recieves it as base64. And this setting has no impact end user mails. They always recieves same garbage.

Can anyone help me understand what could be issue and how to resolve it


问:
How can I use bootstrap modal, toasty, etc. In aspnet core with angular 2 project?
I am using Angular2 in my existing ASP.NET Core MVC project. I am already using toasty, modals and other libraries in my MVC .cshtml views.

However, I couldn't make those work in my components. Is there any example teaching how to use them.

Tried ngModal and others but could not make it work

答:
There's lots of providers who offer Modals , Pagination and other controls

Try this

http://valor-software.com/ngx-bootstrap/#/modals

It's the easyest to use as I know


问:
Share button in Facebook chatbot in Node.js
I want to implement share button inside my chatbot. On click of share button the message will get shared with selected contact list. Image FB_ChatBot.png is what I am trying to implement inside my chatbot and Share_Btn_Output

This png is output produced by share button clicked.

答:
It's an late update but will save someone usefull time. With help of below code you can show multiple buttons on facebook chatbot. Technology used for development is node js,botbuilder,luis.

```<code>var msg = new builder.Message(session);
            msg.sourceEvent({
                "facebook": {
                    "attachment": {
                        "type": "template",
                        "payload": {
                            "template_type": "button",
                            "text": "You can either hit 'FAQ' to get the help, or head to the Mannual Help for getting help.",
                            "buttons": [
                                {
                                    "type": "web_url",
                                    "url": 'https://stackoverflow.com/',
                                    "title": "Mannual Help"
                                },
                                {
                                    "type": "postback",
                                    "title": "FAQ",
                                    "payload": "FAQ_SELECTED_BY_USER"
                                }]
                        }
                    }
                }
            });
            session.send(msg);
</code>```

Body:
It's an late update but will save someone usefull time. With help of below code you can show multiple buttons on facebook chatbot. Technology used for development is node js,botbuilder,luis.

var msg = new builder.Message(session);
            msg.sourceEvent({
                "facebook": {
                    "attachment": {
                        "type": "template",
                        "payload": {
                            "template_type": "button",
                            "text": "You can either hit 'FAQ' to get the help, or head to the Mannual Help for getting help.",
                            "buttons": [
                                {
                                    "type": "web_url",
                                    "url": 'https://stackoverflow.com/',
                                    "title": "Mannual Help"
                                },
                                {
                                    "type": "postback",
                                    "title": "FAQ",
                                    "payload": "FAQ_SELECTED_BY_USER"
                                }]
                        }
                    }
                }
            });
            session.send(msg);


答:
You have to specify that .slideshow-info is a child of this. You do that like so $('.slideshow-info', this)

$(document).ready(function() {
  calculateHeight();

  $(window).resize(function() {
    calculateHeight();
  });
});

function calculateHeight() {
  $('.slideshow').each(function() {
    $('.slideshow-info', this).each(function() {
      slideInfoHeight = $(this).height();
    });
    $('.slideshow-image', this).each(function() {
      slideImageHeight = $(this).height();
    });

    if (slideInfoHeight > slideImageHeight) {
      alert('info is taller than image');
      $('.slideshow-info', this).css('background-color', 'red');
    } else {
      alert('info is shorter than image');
      $('.slideshow-info', this).css('background-color', 'blue');
    }
  });
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slideshow" data-id="1">
  <div class="slideshow-info">
    <h1>
      Header
    </h1>
    <p>
      Text
    </p>
  </div>
  <div class="slideshow-image">
    <img src="https://www.w3schools.com/css/img_fjords.jpg" />
  </div>
</div>
<div class="slideshow" data-id="1">
  <div class="slideshow-info">
    <h1>
      Header
    </h1>
    <p>
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text.
    </p>
  </div>
  <div class="slideshow-image">
    <img src="https://www.w3schools.com/css/img_fjords.jpg" />
  </div>
</div></code>```

Title: How to apply separate CSS styles to divs in a loop with JS?

Body:
You have to specify that .slideshow-info is a child of this. You do that like so $('.slideshow-info', this)

$(document).ready(function() {
  calculateHeight();

  $(window).resize(function() {
    calculateHeight();
  });
});

function calculateHeight() {
  $('.slideshow').each(function() {
    $('.slideshow-info', this).each(function() {
      slideInfoHeight = $(this).height();
    });
    $('.slideshow-image', this).each(function() {
      slideImageHeight = $(this).height();
    });

    if (slideInfoHeight > slideImageHeight) {
      alert('info is taller than image');
      $('.slideshow-info', this).css('background-color', 'red');
    } else {
      alert('info is shorter than image');
      $('.slideshow-info', this).css('background-color', 'blue');
    }
  });
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slideshow" data-id="1">
  <div class="slideshow-info">
    <h1>
      Header
    </h1>
    <p>
      Text
    </p>
  </div>
  <div class="slideshow-image">
    <img src="https://www.w3schools.com/css/img_fjords.jpg" />
  </div>
</div>
<div class="slideshow" data-id="1">
  <div class="slideshow-info">
    <h1>
      Header
    </h1>
    <p>
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text. Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text. Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
      Text Text Text Text.
    </p>
  </div>
  <div class="slideshow-image">
    <img src="https://www.w3schools.com/css/img_fjords.jpg" />
  </div>
</div>


问:
Groovy static compilation (@CompileStatic) turns types of class fields into `Object`
Compiling the following Groovy class

```<code>@CompileStatic
class StaticCompileTest {

   private def fieldInt = 3

}
</code>```

results in this class, when decompiling the .class file:

```<code>public class StaticCompileTest implements GroovyObject {
    private Object fieldInt;
}
</code>```

Changing the field to be final does not change the situation.

Why is the Groovy compiler in this case not able to derive the type?

答:
Because it's inherently unsafe to assume that the type won't change.

see http://docs.groovy-lang.org/latest/html/documentation/#_variables_vs_fields_in_type_inference

Body:
Compiling the following Groovy class

@CompileStatic
class StaticCompileTest {

   private def fieldInt = 3

}

results in this class, when decompiling the .class file:

public class StaticCompileTest implements GroovyObject {
    private Object fieldInt;
}

Changing the field to be final does not change the situation.

Why is the Groovy compiler in this case not able to derive the type?


问:
Cloud Function for Firebase timeout after 60 seconds while running a bunch of Firebase queries
I am using Firebase for a group collaboration app (like Whatsapp) and I am using a Cloud Function to figure out which of the phone contacts are also using my app (again similar to Whatsapp). The Cloud Function ran fine till I started to see the following log in the Functions Log for some invocations.

Function execution took 60023 ms, finished with status: 'timeout'

I did some debugging and found that for this particular user, he has a lot of contacts on his phone's contacts book and so obviously the work required to figure out which of those contacts are using the app also increased to a point that it took more than 60 secs. Below is the code for the Cloud Function

```<code>      // contactsData is an array of contacts on the user's phone
      // Each contact can contain one more phone numbers which are
      // present in the phoneNumbers array. So, essentially, we need
      // to query over all the phone numbers in the user's contact book
      contactsData.forEach((contact) => {
        contact.phoneNumbers.forEach((phoneNumber) => {
          // Find if user with this phoneNumber is using the app
          // Check against mobileNumber and mobileNumberWithCC
          promises.push(ref.child('users').orderByChild("mobileNumber").
            equalTo(phoneNumber.number).once("value").then(usersSnapshot => {
              // usersSnapshot should contain just one entry assuming
              // that the phoneNumber will be unique to the user
              if(!usersSnapshot.exists()) {
                return null
              }
              var user = null
              usersSnapshot.forEach(userSnapshot => {
                user = userSnapshot.val()
              })
              return {
                name: contact.name,
                mobileNumber: phoneNumber.number,
                id: user.id
              }
            }))
          promises.push(ref.child('users').orderByChild("mobileNumberWithCC").
            equalTo(phoneNumber.number).once("value").then(usersSnapshot => {
              // usersSnapshot should contain just one entry assuming
              // that the phoneNumber will be unique to the user
              if(!usersSnapshot.exists()) {
                return null
              }
              var user = null
              usersSnapshot.forEach(userSnapshot => {
                user = userSnapshot.val()
              })
              return {
                name: contact.name,
                mobileNumber: phoneNumber.number,
                id: user.id
              }
            }))
        });
      });
      return Promise.all(promises)
    }).then(allContacts => {
      // allContacts is an array of nulls and contacts using the app
      // Get rid of null and any duplicate entries in the returned array
      currentContacts = arrayCompact(allContacts)

      // Create contactsObj which will the user's contacts that are using the app
      currentContacts.forEach(contact => {
        contactsObj[contact.id] = contact
      })
      // Return the currently present contacts
      return ref.child('userInfos').child(uid).child('contacts').once('value')
    }).then((contactsSnapshot) => {
      if(contactsSnapshot.exists()) {
        contactsSnapshot.forEach((contactSnapshot) => {
          previousContacts.push(contactSnapshot.val())
        })
      }
      // Update the contacts on firease asap after reading the previous contacts
      ref.child('userInfos').child(uid).child('contacts').set(contactsObj)

      // Figure out the new, deleted and renamed contacts
      newContacts = arrayDifferenceWith(currentContacts, previousContacts,
        (obj1, obj2) => (obj1.id === obj2.id))
      deletedContacts = arrayDifferenceWith(previousContacts, currentContacts,
        (obj1, obj2) => (obj1.id === obj2.id))
      renamedContacts = arrayIntersectionWith(currentContacts, previousContacts,
        (obj1, obj2) => (obj1.id === obj2.id && obj1.name !== obj2.name))
      // Create the deletedContactsObj to store on firebase
      deletedContacts.forEach((deletedContact) => {
        deletedContactsObj[deletedContact.id] = deletedContact
      })
      // Get the deleted contacts
      return ref.child('userInfos').child(uid).child('deletedContacts').once('value')
    }).then((deletedContactsSnapshot) => {
      if(deletedContactsSnapshot.exists()) {
        deletedContactsSnapshot.forEach((deletedContactSnapshot) => {
          previouslyDeletedContacts.push(deletedContactSnapshot.val())
        })
      }
      // Contacts that were previously deleted but now added again
      restoredContacts = arrayIntersectionWith(newContacts, previouslyDeletedContacts,
        (obj1, obj2) => (obj1.id === obj2.id))
      // Removed the restored contacts from the deletedContacts
      restoredContacts.forEach((restoredContact) => {
        deletedContactsObj[restoredContact.id] = null
      })
      // Update groups using any of the deleted, new or renamed contacts
      return ContactsHelper.processContactsData(uid, deletedContacts, newContacts, renamedContacts)
    }).then(() => {
      // Set after retrieving the previously deletedContacts
      return ref.child('userInfos').child(uid).child('deletedContacts').update(deletedContactsObj)
    })
</code>```

Below is some sample data

```<code>// This is a sample contactsData
[
  {
    "phoneNumbers": [
      {
        "number": "12324312321",
        "label": "home"
      },
      {
        "number": "2322412132",
        "label": "work"
      }
    ],
    "givenName": "blah5",
    "familyName": "",
    "middleName": ""
  },
  {
    "phoneNumbers": [
      {
        "number": "1231221221",
        "label": "mobile"
      }
    ],
    "givenName": "blah3",
    "familyName": "blah4",
    "middleName": ""
  },
  {
    "phoneNumbers": [
      {
        "number": "1234567890",
        "label": "mobile"
      }
    ],
    "givenName": "blah1",
    "familyName": "blah2",
    "middleName": ""
  }
]

// This is how users are stored on Firebase. This could a lot of users
  "users": {
    "id1" : {
      "countryCode" : "91",
      "id" : "id1",
      "mobileNumber" : "1231211232",
      "mobileNumberWithCC" : "911231211232",
      "name" : "Varun"
    },
    "id2" : {
      "countryCode" : "1",
      "id" : "id2",
      "mobileNumber" : "2342112133",
      "mobileNumberWithCC" : "12342112133",
      "name" : "Ashish"
    },
    "id3" : {
      "countryCode" : "1",
      "id" : "id3",
      "mobileNumber" : "123213421",
      "mobileNumberWithCC" : "1123213421",
      "name" : "Pradeep Singh"
    }
  }
</code>```

In this particular case, the contactsData contained 1046 entries and for some of those entries, there were two phoneNumbers. So, let's assume there were a total of 1500 phone numbers that I need to check. I am creating queries to compare against the mobileNumber and mobileNumberWithCC for the users in the database. So, there are a total of 3000 queries that the function will make before the promise finishes and I am guessing it is taking more than 60 seconds to finish up all those queries and hence the Cloud Function timed out.

My few questions are:

Is it expected for all those queries to take more than 60 secs? I was expecting it to finish much faster given that it is running within the Firebase infrastructure.

Is there a way to increase the timeout limit for a function? I am currently on Blaze plan.

I will also appreciate any alternate implementation suggestions for the above function in order alleviate the problem. Thanks!

答:
The Problem

Your performance problem you experience comes from the query  ref.child('users').orderByChild("mobileNumber").equalTo(phoneNumber.number).once("value") which you are calling from within a forEach() inside another forEach().

To break down this query, you are essentially asking the database to iterate through the children of /users, compare the key mobileNumber to phoneNumber.number and if they match, return a value. However, not only are you calling this for both mobileNumber and mobileNumberWithCC, you are calling this on every iteration of forEach(). So this means that you are looking over X amount of users for Y amount of phone numbers, for Z amount of contacts, therefore performing up to X*Y*Z internal database operations. This is obviously taxing and hence why your query takes over 60 seconds to process.

Potential Fix

I would recommend implementing an index on your database, called /phoneNumbers. Each key in /phoneNumbers is to be named n########### or c########### and contains an "array" of user IDs associated with that phone number.

This structure would look similar to:

```<code>"phoneNumbers": {
  "n1234567890": { // without CC, be warned of overlap
    "userId1": true,
    "userId3": true
  },
  "c011234567890": { // with CC for US
    "userId1": true
  },
  "c611234567890": { // with CC for AU
    "userId3": true
  },
  ...
}
</code>```

Notes:

Why are the phone numbers stored in the format n########### and c###########?

This is because Firebase treats numeric keys as indexes of an array. This doesn't make sense for this use case, so we add the n/c at the start to suppress this behaviour.

Why use both n########### and c###########?

If all entries simply used a n prefix, an 11-digit phone number might overlap with a 10-digit phone number that has it's country code added. So we use n for normal phone numbers and c for numbers that include their country code.

Why did you say that each key of /phoneNumbers contains an "array" of user IDs?

This is because you should avoid using numeric-index arrays in Firebase databases (and arrays in general). Say that two separate processes wanted to update /phoneNumbers/n1234567890 by removing user IDs. If one wants to remove the ID at position 1 and the other at position 2; they would end up removing the IDs at position 1 and 3 instead. This can be overcome by storing the user ID as the key instead which allows you to add/remove it by ID rather than position.

Implementation

As you are already using Cloud Functions, implementing such an index is relatively simple. This code can easily be adapted to suit any sort of automatically generated index based on user data.

```<code>// Initialize functions and admin.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

/**
 * Listens to operations on the children of `/users` and updates the `/phoneNumbers` index appropriately.
 */
exports.handleNewUser = functions.database.ref('/users/{userId}')
  .onWrite(event => {
    var deltaSnapshot = event.data,
        userId = event.params.userId,
        tasks = []; // for returned promises

    if (!deltaSnapshot.exists()) {
      // This user has been deleted.
      var previousData = deltaSnapshot.previous.val();
      if (previousData.number) {
        tasks.push(removeUserFromPhoneNumber(userId, previousData.number, false));
      }
      if (previousData.numberWithCC) {
        tasks.push(removeUserFromPhoneNumber(userId, previousData.numberWithCC, true));
      }
      // Handle other cleanup tasks.
      return Promise.all(tasks).then(() => {
        console.log('User "' + userId + '" deleted successfully.');
      });
    }

    var currentData = deltaSnapshot.val();

    if (deltaSnapshot.previous.exists()) {
      // This is an update to existing data.
      var previousData = deltaSnapshot.previous.val();

      if (currentData.number != previousData.number) { // Phone number changed.
        tasks.push(removeUserFromPhoneNumber(userId, previousData.number, false));
        tasks.push(addUserToPhoneNumber(userId, currentData.number, false));
      }
      if (currentData.numberWithCC != previousData.numberWithCC) { // Phone number changed.
        tasks.push(removeUserFromPhoneNumber(userId, previousData.numberWithCC, true));
        tasks.push(addUserToPhoneNumber(userId, currentData.numberWithCC, true));
      }
      // Handle other tasks related to update.
      return Promise.all(tasks).then(() => {
        console.log('User "' + userId + '" updated successfully.');
      });
    }

    // If here, this is a new user.
    tasks.push(addUserToPhoneNumber(userId, currentData.number, false));
    tasks.push(addUserToPhoneNumber(userId, currentData.numberWithCC, true));
    // Handle other tasks related to addition of new user.
    return Promise.all(tasks).then(() => {
      console.log('User "' + userId + '" created successfully.');
    });
  );

/* Phone Number Index Helper Functions */

/**
 * Returns an array of user IDs linked to the specified phone number.
 * @param {String} number - the phone number
 * @param {Boolean} withCountryCode - true, if the phone number includes a country code
 * @return {Promise} - a promise returning an array of user IDs, may be empty.
 */
function lookupUsersByPhoneNumber(number, withCountryCode) {
  // Error out before corrupting data.
  if (!number) return Promise.reject(new TypeError('number cannot be falsy.');
  return lookupIdsByIndex('phoneNumbers', (withCountryCode ? 'c' : 'n') + number);
}

/**
 * Adds the user ID under the specified phone number's index.
 * @param {String} userId - the user ID
 * @param {String} number - the phone number
 * @param {Boolean} withCountryCode - true, if the phone number includes a country code
 * @return {Promise} - the promise returned by transaction()
 */
function addUserToPhoneNumber(userId, number, withCountryCode) {
  // Error out before corrupting data.
  if (!number) return Promise.reject(new TypeError('number cannot be falsy.');
  return addIdToIndex(userId, 'phoneNumbers', (withCountryCode ? 'c' : 'n') + number)
}

/**
 * Removes the user ID under the specified phone number's index.
 * @param {String} userId - the user ID
 * @param {String} number - the phone number
 * @param {Boolean} withCountryCode - true, if the phone number includes a country code
 * @return {Promise} - the promise returned by transaction()
 */
function removeUserFromPhoneNumber(userId, number, withCountryCode) {
  // Error out before corrupting data.
  if (!number) return Promise.reject(new TypeError('number cannot be falsy.');
  return removeIdFromIndex(userId, 'phoneNumbers', (withCountryCode ? 'c' : 'n') + number)
}

/* General Firebase Index CRUD APIs */
/* Credit: @samthecodingman */

/**
 * Returns an array of IDs linked to the specified key in the given index.
 * @param {String} indexName - the index name
 * @param {String} keyName - the key name
 * @return {Promise} - the promise returned by transaction()
 */
function lookupIdsByIndex(indexName, keyName) {
  // Error out before corrupting data.
  if (!indexName) return Promise.reject(new TypeError('indexName cannot be falsy.');
  if (!keyName) return Promise.reject(new TypeError('keyName cannot be falsy.');
  return admin.database().ref(indexName).child(keyName).once("value")
  .then(snapshot => {
    if (!snapshot.exists()) return []; // Use empty array for 'no data'
    var idsObject = snapshot.val();
    if (idsObject == null) return [];
    return Object.keys(idsObject); // return array of IDs
  });
}

/**
 * Adds the ID to the index under the named key.
 * @param {String} id - the entry ID
 * @param {String} indexName - the index name
 * @param {String} keyName - the key name
 * @return {Promise} - the promise returned by transaction()
 */
function addIdToIndex(id, indexName, keyName) {
  // Error out before corrupting data.
  if (!id) return Promise.reject(new TypeError('id cannot be falsy.');
  if (!indexName) return Promise.reject(new TypeError('indexName cannot be falsy.');
  if (!keyName) return Promise.reject(new TypeError('keyName cannot be falsy.');
  return admin.database().ref(indexName).child(keyName)
  .transaction(function(idsObject) {
    idsObject = idsObject || {}; // Create data if it doesn't exist.
    if (idsObject.hasOwnProperty(id)) return; // No update needed.
    idsObject[id] = true; // Add ID.
    return idsObject;
  });
}

/**
 * Removes the ID from the index under the named key.
 * @param {String} id - the entry ID
 * @param {String} indexName - the index name
 * @param {String} keyName - the key name
 * @return {Promise} - the promise returned by transaction()
 */
function removeIdFromIndex(id, indexName, keyName) {
  // Error out before corrupting data.
  if (!id) return Promise.reject(new TypeError('id cannot be falsy.');
  if (!indexName) return Promise.reject(new TypeError('indexName cannot be falsy.');
  if (!keyName) return Promise.reject(new TypeError('keyName cannot be falsy.');
  return admin.database().ref(indexName).child(keyName)
  .transaction(function(idsObject) {
    if (idsObject === null) return; // No data to update.
    if (!idsObject.hasOwnProperty(id)) return; // No update needed.
    delete idsObject[id]; // Remove ID.
    if (Object.keys(idsObject).length === 0) return null; // Delete entire entry.
    return idsObject;
  });
}
</code>```

The handleNewUser function in the above snippet doesn't catch errors. It will just let Firebase deal with them (by default FB will just log the error). I would recommend implementing appropriate fallbacks as you desire (as you should with any Cloud Function).

Regarding the source code in your question, it would become something similar to:

```<code>contactsData.forEach((contact) => {
  contact.phoneNumbers.forEach((phoneNumber) => {
    var tasks = [];
    tasks.push(lookupUsersByPhoneNumber(phoneNumber.number, false)); // Lookup without CC
    tasks.push(lookupUsersByPhoneNumber(phoneNumber.number, true)); // Lookup with CC
    Promise.all(tasks).then(taskResults => {
      var i = 0;
      // Elements of taskResults are arrays of strings from the lookup functions.
      // Flatten and dedupe strings arrays
      var userIds = taskResults.reduce((arr, results) => {
        for (i=0;i<results.length;i++) {
          if (results[i] !== null && ~arr.indexOf(results[i])) {
            arr.push(results[i]); // Add if not already added.
          }
        }
        return arr;
      }, []);

      // Build 'contacts' array (Doesn't need a database lookup!)
      return userIds.map(uid => ({
        name: contact.name,
        phone: phoneNumber.number,
        id: uid
      }));
    }).then(currentContacts => {
      currentContacts.forEach(contact => {
        contactsObj[contact.id] = contact
      });

      // do original code from question here.
      // I'm not 100% on what it does, so I'll leave it to you.
      // It currently uses an array which is a bad implementation (see notes above). Use PUSH to update the contacts rather than deleting and readding them constantly.
    });
  });
});
</code>```

Note on Security/Privacy

I would highly recommend restricting read and write access of /phoneNumbers to just the cloud functions service worker for privacy reasons. This may also require portions of your program logic to be moved to the server depending on permissions problems.

To achieve this, replace:

```<code>admin.initializeApp(functions.config().firebase);
</code>```

with:

```<code>admin.initializeApp(Object.assign({}, functions.config().firebase, {
  databaseAuthVariableOverride: {
    uid: "cloudfunc-service-worker" // change as desired
  }
});
</code>```

and to enable it, you would need to configure your Firebase Database rules as follows:

```<code>"rules": {
    "phoneNumbers": {
      ".read": "'cloudfunc-service-worker' === auth.uid",
      ".write": "'cloudfunc-service-worker' === auth.uid"
    }
  }
</code>```

Body:
I am using Firebase for a group collaboration app (like Whatsapp) and I am using a Cloud Function to figure out which of the phone contacts are also using my app (again similar to Whatsapp). The Cloud Function ran fine till I started to see the following log in the Functions Log for some invocations.

Function execution took 60023 ms, finished with status: 'timeout'

I did some debugging and found that for this particular user, he has a lot of contacts on his phone's contacts book and so obviously the work required to figure out which of those contacts are using the app also increased to a point that it took more than 60 secs. Below is the code for the Cloud Function

      // contactsData is an array of contacts on the user's phone
      // Each contact can contain one more phone numbers which are
      // present in the phoneNumbers array. So, essentially, we need
      // to query over all the phone numbers in the user's contact book
      contactsData.forEach((contact) => {
        contact.phoneNumbers.forEach((phoneNumber) => {
          // Find if user with this phoneNumber is using the app
          // Check against mobileNumber and mobileNumberWithCC
          promises.push(ref.child('users').orderByChild("mobileNumber").
            equalTo(phoneNumber.number).once("value").then(usersSnapshot => {
              // usersSnapshot should contain just one entry assuming
              // that the phoneNumber will be unique to the user
              if(!usersSnapshot.exists()) {
                return null
              }
              var user = null
              usersSnapshot.forEach(userSnapshot => {
                user = userSnapshot.val()
              })
              return {
                name: contact.name,
                mobileNumber: phoneNumber.number,
                id: user.id
              }
            }))
          promises.push(ref.child('users').orderByChild("mobileNumberWithCC").
            equalTo(phoneNumber.number).once("value").then(usersSnapshot => {
              // usersSnapshot should contain just one entry assuming
              // that the phoneNumber will be unique to the user
              if(!usersSnapshot.exists()) {
                return null
              }
              var user = null
              usersSnapshot.forEach(userSnapshot => {
                user = userSnapshot.val()
              })
              return {
                name: contact.name,
                mobileNumber: phoneNumber.number,
                id: user.id
              }
            }))
        });
      });
      return Promise.all(promises)
    }).then(allContacts => {
      // allContacts is an array of nulls and contacts using the app
      // Get rid of null and any duplicate entries in the returned array
      currentContacts = arrayCompact(allContacts)

      // Create contactsObj which will the user's contacts that are using the app
      currentContacts.forEach(contact => {
        contactsObj[contact.id] = contact
      })
      // Return the currently present contacts
      return ref.child('userInfos').child(uid).child('contacts').once('value')
    }).then((contactsSnapshot) => {
      if(contactsSnapshot.exists()) {
        contactsSnapshot.forEach((contactSnapshot) => {
          previousContacts.push(contactSnapshot.val())
        })
      }
      // Update the contacts on firease asap after reading the previous contacts
      ref.child('userInfos').child(uid).child('contacts').set(contactsObj)

      // Figure out the new, deleted and renamed contacts
      newContacts = arrayDifferenceWith(currentContacts, previousContacts,
        (obj1, obj2) => (obj1.id === obj2.id))
      deletedContacts = arrayDifferenceWith(previousContacts, currentContacts,
        (obj1, obj2) => (obj1.id === obj2.id))
      renamedContacts = arrayIntersectionWith(currentContacts, previousContacts,
        (obj1, obj2) => (obj1.id === obj2.id && obj1.name !== obj2.name))
      // Create the deletedContactsObj to store on firebase
      deletedContacts.forEach((deletedContact) => {
        deletedContactsObj[deletedContact.id] = deletedContact
      })
      // Get the deleted contacts
      return ref.child('userInfos').child(uid).child('deletedContacts').once('value')
    }).then((deletedContactsSnapshot) => {
      if(deletedContactsSnapshot.exists()) {
        deletedContactsSnapshot.forEach((deletedContactSnapshot) => {
          previouslyDeletedContacts.push(deletedContactSnapshot.val())
        })
      }
      // Contacts that were previously deleted but now added again
      restoredContacts = arrayIntersectionWith(newContacts, previouslyDeletedContacts,
        (obj1, obj2) => (obj1.id === obj2.id))
      // Removed the restored contacts from the deletedContacts
      restoredContacts.forEach((restoredContact) => {
        deletedContactsObj[restoredContact.id] = null
      })
      // Update groups using any of the deleted, new or renamed contacts
      return ContactsHelper.processContactsData(uid, deletedContacts, newContacts, renamedContacts)
    }).then(() => {
      // Set after retrieving the previously deletedContacts
      return ref.child('userInfos').child(uid).child('deletedContacts').update(deletedContactsObj)
    })

Below is some sample data

// This is a sample contactsData
[
  {
    "phoneNumbers": [
      {
        "number": "12324312321",
        "label": "home"
      },
      {
        "number": "2322412132",
        "label": "work"
      }
    ],
    "givenName": "blah5",
    "familyName": "",
    "middleName": ""
  },
  {
    "phoneNumbers": [
      {
        "number": "1231221221",
        "label": "mobile"
      }
    ],
    "givenName": "blah3",
    "familyName": "blah4",
    "middleName": ""
  },
  {
    "phoneNumbers": [
      {
        "number": "1234567890",
        "label": "mobile"
      }
    ],
    "givenName": "blah1",
    "familyName": "blah2",
    "middleName": ""
  }
]

// This is how users are stored on Firebase. This could a lot of users
  "users": {
    "id1" : {
      "countryCode" : "91",
      "id" : "id1",
      "mobileNumber" : "1231211232",
      "mobileNumberWithCC" : "911231211232",
      "name" : "Varun"
    },
    "id2" : {
      "countryCode" : "1",
      "id" : "id2",
      "mobileNumber" : "2342112133",
      "mobileNumberWithCC" : "12342112133",
      "name" : "Ashish"
    },
    "id3" : {
      "countryCode" : "1",
      "id" : "id3",
      "mobileNumber" : "123213421",
      "mobileNumberWithCC" : "1123213421",
      "name" : "Pradeep Singh"
    }
  }

In this particular case, the contactsData contained 1046 entries and for some of those entries, there were two phoneNumbers. So, let's assume there were a total of 1500 phone numbers that I need to check. I am creating queries to compare against the mobileNumber and mobileNumberWithCC for the users in the database. So, there are a total of 3000 queries that the function will make before the promise finishes and I am guessing it is taking more than 60 seconds to finish up all those queries and hence the Cloud Function timed out.

My few questions are:

Is it expected for all those queries to take more than 60 secs? I was expecting it to finish much faster given that it is running within the Firebase infrastructure.

Is there a way to increase the timeout limit for a function? I am currently on Blaze plan.

I will also appreciate any alternate implementation suggestions for the above function in order alleviate the problem. Thanks!

Body:
The Problem

Your performance problem you experience comes from the query  ref.child('users').orderByChild("mobileNumber").equalTo(phoneNumber.number).once("value") which you are calling from within a forEach() inside another forEach().

To break down this query, you are essentially asking the database to iterate through the children of /users, compare the key mobileNumber to phoneNumber.number and if they match, return a value. However, not only are you calling this for both mobileNumber and mobileNumberWithCC, you are calling this on every iteration of forEach(). So this means that you are looking over X amount of users for Y amount of phone numbers, for Z amount of contacts, therefore performing up to X*Y*Z internal database operations. This is obviously taxing and hence why your query takes over 60 seconds to process.

Potential Fix

I would recommend implementing an index on your database, called /phoneNumbers. Each key in /phoneNumbers is to be named n########### or c########### and contains an "array" of user IDs associated with that phone number.

This structure would look similar to:

"phoneNumbers": {
  "n1234567890": { // without CC, be warned of overlap
    "userId1": true,
    "userId3": true
  },
  "c011234567890": { // with CC for US
    "userId1": true
  },
  "c611234567890": { // with CC for AU
    "userId3": true
  },
  ...
}

Notes:

Why are the phone numbers stored in the format n########### and c###########?

This is because Firebase treats numeric keys as indexes of an array. This doesn't make sense for this use case, so we add the n/c at the start to suppress this behaviour.

Why use both n########### and c###########?

If all entries simply used a n prefix, an 11-digit phone number might overlap with a 10-digit phone number that has it's country code added. So we use n for normal phone numbers and c for numbers that include their country code.

Why did you say that each key of /phoneNumbers contains an "array" of user IDs?

This is because you should avoid using numeric-index arrays in Firebase databases (and arrays in general). Say that two separate processes wanted to update /phoneNumbers/n1234567890 by removing user IDs. If one wants to remove the ID at position 1 and the other at position 2; they would end up removing the IDs at position 1 and 3 instead. This can be overcome by storing the user ID as the key instead which allows you to add/remove it by ID rather than position.

Implementation

As you are already using Cloud Functions, implementing such an index is relatively simple. This code can easily be adapted to suit any sort of automatically generated index based on user data.

// Initialize functions and admin.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

/**
 * Listens to operations on the children of `/users` and updates the `/phoneNumbers` index appropriately.
 */
exports.handleNewUser = functions.database.ref('/users/{userId}')
  .onWrite(event => {
    var deltaSnapshot = event.data,
        userId = event.params.userId,
        tasks = []; // for returned promises

    if (!deltaSnapshot.exists()) {
      // This user has been deleted.
      var previousData = deltaSnapshot.previous.val();
      if (previousData.number) {
        tasks.push(removeUserFromPhoneNumber(userId, previousData.number, false));
      }
      if (previousData.numberWithCC) {
        tasks.push(removeUserFromPhoneNumber(userId, previousData.numberWithCC, true));
      }
      // Handle other cleanup tasks.
      return Promise.all(tasks).then(() => {
        console.log('User "' + userId + '" deleted successfully.');
      });
    }

    var currentData = deltaSnapshot.val();

    if (deltaSnapshot.previous.exists()) {
      // This is an update to existing data.
      var previousData = deltaSnapshot.previous.val();

      if (currentData.number != previousData.number) { // Phone number changed.
        tasks.push(removeUserFromPhoneNumber(userId, previousData.number, false));
        tasks.push(addUserToPhoneNumber(userId, currentData.number, false));
      }
      if (currentData.numberWithCC != previousData.numberWithCC) { // Phone number changed.
        tasks.push(removeUserFromPhoneNumber(userId, previousData.numberWithCC, true));
        tasks.push(addUserToPhoneNumber(userId, currentData.numberWithCC, true));
      }
      // Handle other tasks related to update.
      return Promise.all(tasks).then(() => {
        console.log('User "' + userId + '" updated successfully.');
      });
    }

    // If here, this is a new user.
    tasks.push(addUserToPhoneNumber(userId, currentData.number, false));
    tasks.push(addUserToPhoneNumber(userId, currentData.numberWithCC, true));
    // Handle other tasks related to addition of new user.
    return Promise.all(tasks).then(() => {
      console.log('User "' + userId + '" created successfully.');
    });
  );

/* Phone Number Index Helper Functions */

/**
 * Returns an array of user IDs linked to the specified phone number.
 * @param {String} number - the phone number
 * @param {Boolean} withCountryCode - true, if the phone number includes a country code
 * @return {Promise} - a promise returning an array of user IDs, may be empty.
 */
function lookupUsersByPhoneNumber(number, withCountryCode) {
  // Error out before corrupting data.
  if (!number) return Promise.reject(new TypeError('number cannot be falsy.');
  return lookupIdsByIndex('phoneNumbers', (withCountryCode ? 'c' : 'n') + number);
}

/**
 * Adds the user ID under the specified phone number's index.
 * @param {String} userId - the user ID
 * @param {String} number - the phone number
 * @param {Boolean} withCountryCode - true, if the phone number includes a country code
 * @return {Promise} - the promise returned by transaction()
 */
function addUserToPhoneNumber(userId, number, withCountryCode) {
  // Error out before corrupting data.
  if (!number) return Promise.reject(new TypeError('number cannot be falsy.');
  return addIdToIndex(userId, 'phoneNumbers', (withCountryCode ? 'c' : 'n') + number)
}

/**
 * Removes the user ID under the specified phone number's index.
 * @param {String} userId - the user ID
 * @param {String} number - the phone number
 * @param {Boolean} withCountryCode - true, if the phone number includes a country code
 * @return {Promise} - the promise returned by transaction()
 */
function removeUserFromPhoneNumber(userId, number, withCountryCode) {
  // Error out before corrupting data.
  if (!number) return Promise.reject(new TypeError('number cannot be falsy.');
  return removeIdFromIndex(userId, 'phoneNumbers', (withCountryCode ? 'c' : 'n') + number)
}

/* General Firebase Index CRUD APIs */
/* Credit: @samthecodingman */

/**
 * Returns an array of IDs linked to the specified key in the given index.
 * @param {String} indexName - the index name
 * @param {String} keyName - the key name
 * @return {Promise} - the promise returned by transaction()
 */
function lookupIdsByIndex(indexName, keyName) {
  // Error out before corrupting data.
  if (!indexName) return Promise.reject(new TypeError('indexName cannot be falsy.');
  if (!keyName) return Promise.reject(new TypeError('keyName cannot be falsy.');
  return admin.database().ref(indexName).child(keyName).once("value")
  .then(snapshot => {
    if (!snapshot.exists()) return []; // Use empty array for 'no data'
    var idsObject = snapshot.val();
    if (idsObject == null) return [];
    return Object.keys(idsObject); // return array of IDs
  });
}

/**
 * Adds the ID to the index under the named key.
 * @param {String} id - the entry ID
 * @param {String} indexName - the index name
 * @param {String} keyName - the key name
 * @return {Promise} - the promise returned by transaction()
 */
function addIdToIndex(id, indexName, keyName) {
  // Error out before corrupting data.
  if (!id) return Promise.reject(new TypeError('id cannot be falsy.');
  if (!indexName) return Promise.reject(new TypeError('indexName cannot be falsy.');
  if (!keyName) return Promise.reject(new TypeError('keyName cannot be falsy.');
  return admin.database().ref(indexName).child(keyName)
  .transaction(function(idsObject) {
    idsObject = idsObject || {}; // Create data if it doesn't exist.
    if (idsObject.hasOwnProperty(id)) return; // No update needed.
    idsObject[id] = true; // Add ID.
    return idsObject;
  });
}

/**
 * Removes the ID from the index under the named key.
 * @param {String} id - the entry ID
 * @param {String} indexName - the index name
 * @param {String} keyName - the key name
 * @return {Promise} - the promise returned by transaction()
 */
function removeIdFromIndex(id, indexName, keyName) {
  // Error out before corrupting data.
  if (!id) return Promise.reject(new TypeError('id cannot be falsy.');
  if (!indexName) return Promise.reject(new TypeError('indexName cannot be falsy.');
  if (!keyName) return Promise.reject(new TypeError('keyName cannot be falsy.');
  return admin.database().ref(indexName).child(keyName)
  .transaction(function(idsObject) {
    if (idsObject === null) return; // No data to update.
    if (!idsObject.hasOwnProperty(id)) return; // No update needed.
    delete idsObject[id]; // Remove ID.
    if (Object.keys(idsObject).length === 0) return null; // Delete entire entry.
    return idsObject;
  });
}

The handleNewUser function in the above snippet doesn't catch errors. It will just let Firebase deal with them (by default FB will just log the error). I would recommend implementing appropriate fallbacks as you desire (as you should with any Cloud Function).

Regarding the source code in your question, it would become something similar to:

contactsData.forEach((contact) => {
  contact.phoneNumbers.forEach((phoneNumber) => {
    var tasks = [];
    tasks.push(lookupUsersByPhoneNumber(phoneNumber.number, false)); // Lookup without CC
    tasks.push(lookupUsersByPhoneNumber(phoneNumber.number, true)); // Lookup with CC
    Promise.all(tasks).then(taskResults => {
      var i = 0;
      // Elements of taskResults are arrays of strings from the lookup functions.
      // Flatten and dedupe strings arrays
      var userIds = taskResults.reduce((arr, results) => {
        for (i=0;i<results.length;i++) {
          if (results[i] !== null && ~arr.indexOf(results[i])) {
            arr.push(results[i]); // Add if not already added.
          }
        }
        return arr;
      }, []);

      // Build 'contacts' array (Doesn't need a database lookup!)
      return userIds.map(uid => ({
        name: contact.name,
        phone: phoneNumber.number,
        id: uid
      }));
    }).then(currentContacts => {
      currentContacts.forEach(contact => {
        contactsObj[contact.id] = contact
      });

      // do original code from question here.
      // I'm not 100% on what it does, so I'll leave it to you.
      // It currently uses an array which is a bad implementation (see notes above). Use PUSH to update the contacts rather than deleting and readding them constantly.
    });
  });
});

Note on Security/Privacy

I would highly recommend restricting read and write access of /phoneNumbers to just the cloud functions service worker for privacy reasons. This may also require portions of your program logic to be moved to the server depending on permissions problems.

To achieve this, replace:

admin.initializeApp(functions.config().firebase);

with:

admin.initializeApp(Object.assign({}, functions.config().firebase, {
  databaseAuthVariableOverride: {
    uid: "cloudfunc-service-worker" // change as desired
  }
});

and to enable it, you would need to configure your Firebase Database rules as follows:

"rules": {
    "phoneNumbers": {
      ".read": "'cloudfunc-service-worker' === auth.uid",
      ".write": "'cloudfunc-service-worker' === auth.uid"
    }
  }


问:
What is the Origin (the start point when learning was started) of an Area Description File in Tango Service
AreaLearning Documentation says that after Localization in an ADF (Area Description File) the Tango Services knows exactly where the Device is w.r.t ADF's Origin (the start point when learning was started).

I'm creating an Indoor map application using Tango in Unity3D & I want to align the ADF's Origin with Unity's World Space Origin(0,0,0); so that the localized position exactly matches with the Map.

Any help please.
Thanks in Advance.

答:
I'm working in Tango Java API but I think my answer will help you.

For me, I succeeded in place a cube to the origin in the scene of camera.

screen shot of the scene

In this figure, the origin 1 is the place where I began my localization and origin 2 is where the exploration began.

In fact, I've done this:
1.Create a renderer for the scene (example in Java Augmented Reality)
2.register a callback that: first set up scene camera projection to match the camera then get the frame pose for the renderer
3.Update the position of the cube (fix 0, 0, 0 for the origin 1)(Area learning - first pair)

For your question, you need to align the coordinate system of camera used in Unity3D and Tango Service.

Hope that my answer help.


问:
Sort array by date php
Array keys are date and want to sort array by date in Asending order. Following is array:</p>

```<code>Array
(
    [07/14/2017] => Array
        (
            [ID] => 5442
            [post_content] => Test1
            [post_title] => Testevents1
        )

    [01/11/2017] => Array
        (
            [ID] => 5443
            [post_content] => Test2
            [post_title] => Testevents2
        )
)
</code>```

答:
You can use uksort for this.

uksort — Sort an array by keys using a user-defined comparison function

```<code>function cmp($keyA, $keyB)
{
    // Your date parsing and comparison

    // The comparison function must return an integer less than, equal to,
    // or greater than zero if the first argument is considered to be respectively
    // less than, equal to, or greater than the second.
    // Note that before PHP 7.0.0 this integer had to be in the range
    // from -2147483648 to 2147483647.
}

uksort($arr, "cmp")
</code>```

Title: Sort array by date php

Body:
Array keys are date and want to sort array by date in Asending order. Following is array:

Array
(
    [07/14/2017] => Array
        (
            [ID] => 5442
            [post_content] => Test1
            [post_title] => Testevents1
        )

    [01/11/2017] => Array
        (
            [ID] => 5443
            [post_content] => Test2
            [post_title] => Testevents2
        )
)

Body:
You can use uksort for this.

uksort — Sort an array by keys using a user-defined comparison function

function cmp($keyA, $keyB)
{
    // Your date parsing and comparison

    // The comparison function must return an integer less than, equal to,
    // or greater than zero if the first argument is considered to be respectively
    // less than, equal to, or greater than the second.
    // Note that before PHP 7.0.0 this integer had to be in the range
    // from -2147483648 to 2147483647.
}

uksort($arr, "cmp")


问:
TextView in LinearLayout pushed outside by another TextView
Good day! I am trying to achieve a specific kind of layout. I hope somebody could give me a hint on how to do it properly.

So, inside my layout, I have two TextView inside of a LinearLayout with horizontal orientation. The first TextView contains the name of the company and the second contains a number of the projects associated with it.

I wanted my layout to behave like this.

My current layout looks like this.

Here's the specific code for the layout:

```<code><LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/contractor_item_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:maxLines="1"
        android:text="Gem Seeker Company and  Supplies in"
        android:textColor="@color/list_title"
        android:textSize="16sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="(0)"
        android:textSize="16sp"
        android:textStyle="bold"
        android:maxLines="1"
        android:layout_marginStart="4dp"
        android:textColor="@color/space_gray_01"/>

</LinearLayout>
</code>```

Heres the complete code of the layout:

```<code><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginEnd="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:background="@android:color/white"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/contractor_item_layout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:clickable="true"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/contractor_item_avatar"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:background="@color/space_gray_01"
            android:contentDescription="@string/image_description"
            android:src="@drawable/ic_user_light" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="16dp">

            <TextView
                android:id="@+id/contractor_item_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:visibility="gone" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/contractor_item_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:ellipsize="end"
                    android:maxLines="1"
                    android:text="Gem Seeker Company and  Supplies in"
                    android:textColor="@color/list_title"
                    android:textSize="16sp" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="(0)"
                    android:textSize="16sp"
                    android:textStyle="bold"
                    android:maxLines="1"
                    android:layout_marginStart="4dp"
                    android:textColor="@color/space_gray_01"/>

            </LinearLayout>

            <TextView
                android:id="@+id/contractor_item_address"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:maxLines="1"
                android:text="@string/text_no_address"
                android:textColor="@color/list_subtitle"
                android:textSize="14sp" />

            <TextView
                android:id="@+id/contractor_item_phone"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/text_no_contact"
                android:textColor="@color/list_subtitle"
                android:textSize="14sp" />

        </LinearLayout>

    </LinearLayout>

    <ImageView
        android:id="@+id/contractor_item_show"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_marginTop="8dp"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:clickable="true"
        android:contentDescription="@string/image_description"
        android:src="@drawable/ic_show"
        android:tint="@color/space_gray_02" />

</LinearLayout>
</code>```

答: You need to declare weightsum inside horizontal linear layout and distribute layout weight to inside widgets </p>

Body:
Good day! I am trying to achieve a specific kind of layout. I hope somebody could give me a hint on how to do it properly.

So, inside my layout, I have two TextView inside of a LinearLayout with horizontal orientation. The first TextView contains the name of the company and the second contains a number of the projects associated with it.

I wanted my layout to behave like this.

My current layout looks like this.

Here's the specific code for the layout:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/contractor_item_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:maxLines="1"
        android:text="Gem Seeker Company and  Supplies in"
        android:textColor="@color/list_title"
        android:textSize="16sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="(0)"
        android:textSize="16sp"
        android:textStyle="bold"
        android:maxLines="1"
        android:layout_marginStart="4dp"
        android:textColor="@color/space_gray_01"/>

</LinearLayout>

Heres the complete code of the layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginEnd="8dp"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:background="@android:color/white"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/contractor_item_layout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:clickable="true"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/contractor_item_avatar"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:background="@color/space_gray_01"
            android:contentDescription="@string/image_description"
            android:src="@drawable/ic_user_light" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="16dp">

            <TextView
                android:id="@+id/contractor_item_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:visibility="gone" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/contractor_item_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:ellipsize="end"
                    android:maxLines="1"
                    android:text="Gem Seeker Company and  Supplies in"
                    android:textColor="@color/list_title"
                    android:textSize="16sp" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="(0)"
                    android:textSize="16sp"
                    android:textStyle="bold"
                    android:maxLines="1"
                    android:layout_marginStart="4dp"
                    android:textColor="@color/space_gray_01"/>

            </LinearLayout>

            <TextView
                android:id="@+id/contractor_item_address"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:maxLines="1"
                android:text="@string/text_no_address"
                android:textColor="@color/list_subtitle"
                android:textSize="14sp" />

            <TextView
                android:id="@+id/contractor_item_phone"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/text_no_contact"
                android:textColor="@color/list_subtitle"
                android:textSize="14sp" />

        </LinearLayout>

    </LinearLayout>

    <ImageView
        android:id="@+id/contractor_item_show"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_marginTop="8dp"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:clickable="true"
        android:contentDescription="@string/image_description"
        android:src="@drawable/ic_show"
        android:tint="@color/space_gray_02" />

</LinearLayout>


问:
Haystack and Elasticsearch: Limit number of results
I have 2 servers with Haystack:

Server1: This has elasticsearch installed

Server2: This doesn't have elasticsearch, the queries are made to Server1

My issue is about pagination when I make queries from Server2 to Server1:

Server2 makes query to Server1

Server1 send all the results back to Server2

Server2 makes the pagination

But this is not optimal, if the query return 10.000 objects, the query will be slow.

I know that you can send to elasticsearch some values in the query (size, from and to) but I don't know if this is possible using Haystack, I've checked documentation and googled it and found nothing.

How could I configure the query in Haystack to receive the results 10 by 10 ?

Edit

Is possible that if I make SearchQuerySet()[10000:10010] it will only ask for this 10 items ?

Or it will ask for all the items and then filter them ?

Edit2

I found this on Haystack Docs:

SearchQuery API - set_limits

it seems a function to do whatt I'm trying to do:

Restricts the query by altering either the start, end or both offsets.

And then I tried to do:

```<code>from haystack.query import SearchQuerySet

sqs = SearchQuerySet()
sqs.query.set_limits(low=0, high=4)
sqs.filter(content='anything')
</code>```

The result is the full list, like I never add the set_limit line

Why is not working ?

答:
Adding on to the Yigit answer, if you want to have these offsets on filtered records just add filter condition when you form the SearchQuerySet.

Also remember once the limits are set you can't change them by setting them again. You would need to form the SearchQuerySet() again, or there is a method to clear the limits.

```<code>results = SearchQuerySet().filter(content="keyword")
#we have a filtered resultSet now let's find specific records
results.query.set_limits(0,4)
return results.query.get_results()
</code>```

Body:
I have 2 servers with Haystack:

Server1: This has elasticsearch installed

Server2: This doesn't have elasticsearch, the queries are made to Server1

My issue is about pagination when I make queries from Server2 to Server1:

Server2 makes query to Server1

Server1 send all the results back to Server2

Server2 makes the pagination

But this is not optimal, if the query return 10.000 objects, the query will be slow.

I know that you can send to elasticsearch some values in the query (size, from and to) but I don't know if this is possible using Haystack, I've checked documentation and googled it and found nothing.

How could I configure the query in Haystack to receive the results 10 by 10 ?

Edit

Is possible that if I make SearchQuerySet()[10000:10010] it will only ask for this 10 items ?

Or it will ask for all the items and then filter them ?

Edit2

I found this on Haystack Docs:

SearchQuery API - set_limits

it seems a function to do whatt I'm trying to do:

Restricts the query by altering either the start, end or both offsets.

And then I tried to do:

from haystack.query import SearchQuerySet

sqs = SearchQuerySet()
sqs.query.set_limits(low=0, high=4)
sqs.filter(content='anything')

The result is the full list, like I never add the set_limit line

Why is not working ?

Body:
Adding on to the Yigit answer, if you want to have these offsets on filtered records just add filter condition when you form the SearchQuerySet.

Also remember once the limits are set you can't change them by setting them again. You would need to form the SearchQuerySet() again, or there is a method to clear the limits.

results = SearchQuerySet().filter(content="keyword")
#we have a filtered resultSet now let's find specific records
results.query.set_limits(0,4)
return results.query.get_results()